@jmruthers/pace-core 0.5.68 → 0.5.69

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 (375) hide show
  1. package/dist/{DataTable-4IUY7BXB.js → DataTable-MPBSXUC6.js} +5 -6
  2. package/dist/{PublicLoadingSpinner-DdKXTkCZ.d.ts → PublicLoadingSpinner-BOdyU3u-.d.ts} +1 -1
  3. package/dist/{chunk-PXWEDX7Y.js → chunk-2ARQW6VX.js} +3 -3
  4. package/dist/{chunk-MOJXHWDE.js → chunk-6JILXFEA.js} +335 -5
  5. package/dist/chunk-6JILXFEA.js.map +1 -0
  6. package/dist/{chunk-D7ARGIA3.js → chunk-6RBH67W7.js} +23 -6
  7. package/dist/chunk-6RBH67W7.js.map +1 -0
  8. package/dist/{chunk-ZMS23NS5.js → chunk-FJTAWPAQ.js} +3 -5
  9. package/dist/{chunk-ZMS23NS5.js.map → chunk-FJTAWPAQ.js.map} +1 -1
  10. package/dist/{chunk-OPCWH3A4.js → chunk-NO5QHMDX.js} +7 -6
  11. package/dist/chunk-NO5QHMDX.js.map +1 -0
  12. package/dist/{chunk-ZPK5656W.js → chunk-O3NWNXDY.js} +4 -5
  13. package/dist/chunk-O3NWNXDY.js.map +1 -0
  14. package/dist/{chunk-UYA6U6H7.js → chunk-Q2UP3ZWQ.js} +4 -4
  15. package/dist/{chunk-KRCRNXPD.js → chunk-RVYGJPOD.js} +79 -18
  16. package/dist/chunk-RVYGJPOD.js.map +1 -0
  17. package/dist/{chunk-NN45OBIS.js → chunk-UCMHBF7Y.js} +3 -5
  18. package/dist/{chunk-NN45OBIS.js.map → chunk-UCMHBF7Y.js.map} +1 -1
  19. package/dist/{chunk-ZPG4XPV5.js → chunk-V3QO3LL7.js} +5 -7
  20. package/dist/chunk-V3QO3LL7.js.map +1 -0
  21. package/dist/{chunk-U6GPOF6J.js → chunk-ZXJGZLLO.js} +17 -17
  22. package/dist/{chunk-U6GPOF6J.js.map → chunk-ZXJGZLLO.js.map} +1 -1
  23. package/dist/components.d.ts +1 -1
  24. package/dist/components.js +8 -9
  25. package/dist/components.js.map +1 -1
  26. package/dist/hooks.d.ts +1 -1
  27. package/dist/hooks.js +9 -6
  28. package/dist/hooks.js.map +1 -1
  29. package/dist/index.d.ts +3 -3
  30. package/dist/index.js +16 -16
  31. package/dist/index.js.map +1 -1
  32. package/dist/providers.js +5 -7
  33. package/dist/rbac/index.js +5 -6
  34. package/dist/{usePublicRouteParams-CdoFxnJK.d.ts → usePublicRouteParams-Ua1Vz-HG.d.ts} +35 -1
  35. package/dist/utils.d.ts +4 -1
  36. package/dist/utils.js +3 -3
  37. package/docs/DOCUMENTATION_CHECKLIST.md +281 -0
  38. package/docs/README.md +22 -10
  39. package/docs/api/classes/ColumnFactory.md +1 -1
  40. package/docs/api/classes/ErrorBoundary.md +1 -1
  41. package/docs/api/classes/InvalidScopeError.md +1 -1
  42. package/docs/api/classes/MissingUserContextError.md +1 -1
  43. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  44. package/docs/api/classes/PermissionDeniedError.md +1 -1
  45. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  46. package/docs/api/classes/RBACAuditManager.md +1 -1
  47. package/docs/api/classes/RBACCache.md +1 -1
  48. package/docs/api/classes/RBACEngine.md +1 -1
  49. package/docs/api/classes/RBACError.md +1 -1
  50. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  51. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  52. package/docs/api/classes/StorageUtils.md +1 -1
  53. package/docs/api/interfaces/AggregateConfig.md +1 -1
  54. package/docs/api/interfaces/ButtonProps.md +1 -1
  55. package/docs/api/interfaces/CardProps.md +1 -1
  56. package/docs/api/interfaces/ColorPalette.md +1 -1
  57. package/docs/api/interfaces/ColorShade.md +1 -1
  58. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  59. package/docs/api/interfaces/DataTableAction.md +1 -1
  60. package/docs/api/interfaces/DataTableColumn.md +1 -1
  61. package/docs/api/interfaces/DataTableProps.md +1 -1
  62. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  63. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  64. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  65. package/docs/api/interfaces/EventContextType.md +1 -1
  66. package/docs/api/interfaces/EventLogoProps.md +1 -1
  67. package/docs/api/interfaces/EventProviderProps.md +1 -1
  68. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  69. package/docs/api/interfaces/FileUploadProps.md +1 -1
  70. package/docs/api/interfaces/FooterProps.md +1 -1
  71. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  72. package/docs/api/interfaces/InputProps.md +1 -1
  73. package/docs/api/interfaces/LabelProps.md +1 -1
  74. package/docs/api/interfaces/LoginFormProps.md +1 -1
  75. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  76. package/docs/api/interfaces/NavigationContextType.md +1 -1
  77. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  78. package/docs/api/interfaces/NavigationItem.md +1 -1
  79. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  80. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  81. package/docs/api/interfaces/Organisation.md +1 -1
  82. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  83. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  84. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  85. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  86. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  87. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  88. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  89. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  90. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  91. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  92. package/docs/api/interfaces/PaletteData.md +1 -1
  93. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  94. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  95. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  96. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  97. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  98. package/docs/api/interfaces/PublicPageHeaderProps.md +2 -2
  99. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  100. package/docs/api/interfaces/RBACConfig.md +1 -1
  101. package/docs/api/interfaces/RBACContextType.md +1 -1
  102. package/docs/api/interfaces/RBACLogger.md +1 -1
  103. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  104. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  105. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  106. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  107. package/docs/api/interfaces/RouteConfig.md +1 -1
  108. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  109. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  110. package/docs/api/interfaces/StorageConfig.md +1 -1
  111. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  112. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  113. package/docs/api/interfaces/StorageListOptions.md +1 -1
  114. package/docs/api/interfaces/StorageListResult.md +1 -1
  115. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  116. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  117. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  118. package/docs/api/interfaces/StyleImport.md +1 -1
  119. package/docs/api/interfaces/SwitchProps.md +1 -1
  120. package/docs/api/interfaces/ToastActionElement.md +1 -1
  121. package/docs/api/interfaces/ToastProps.md +1 -1
  122. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  123. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  124. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  125. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  126. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  127. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  128. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  129. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  130. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  131. package/docs/api/interfaces/UserEventAccess.md +1 -1
  132. package/docs/api/interfaces/UserMenuProps.md +1 -1
  133. package/docs/api/interfaces/UserProfile.md +1 -1
  134. package/docs/api/modules.md +39 -14
  135. package/docs/architecture/services.md +374 -0
  136. package/docs/best-practices/README.md +1 -1
  137. package/docs/best-practices/testing.md +1 -1
  138. package/docs/breaking-changes.md +182 -0
  139. package/docs/common-patterns.md +445 -0
  140. package/docs/core-concepts/authentication.md +26 -11
  141. package/docs/core-concepts/events.md +2 -0
  142. package/docs/core-concepts/organisations.md +2 -0
  143. package/docs/core-concepts/permissions.md +2 -0
  144. package/docs/{INDEX.md → documentation-index.md} +26 -38
  145. package/docs/faq.md +286 -0
  146. package/docs/{FILE_REFERENCE_SYSTEM.md → file-reference-system.md} +1 -1
  147. package/docs/getting-started/installation-guide.md +284 -0
  148. package/docs/getting-started/quick-start.md +8 -1
  149. package/docs/implementation-guides/app-layout.md +3 -1
  150. package/docs/implementation-guides/data-tables.md +2 -0
  151. package/docs/implementation-guides/dynamic-colors.md +47 -2
  152. package/docs/implementation-guides/event-theming-summary.md +220 -0
  153. package/docs/implementation-guides/forms.md +9 -7
  154. package/docs/implementation-guides/navigation.md +2 -0
  155. package/docs/migration/service-architecture.md +351 -0
  156. package/docs/rbac/README-rbac-rls-integration.md +2 -2
  157. package/docs/rbac/README.md +1 -1
  158. package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
  159. package/docs/rbac/quick-start.md +2 -0
  160. package/docs/rbac/rbac-rls-integration.md +2 -2
  161. package/docs/style-guide.md +136 -1
  162. package/docs/testing/README.md +1 -1
  163. package/docs/troubleshooting/authentication-issues.md +334 -0
  164. package/docs/troubleshooting/common-issues.md +2 -0
  165. package/docs/troubleshooting/styling-issues.md +199 -144
  166. package/docs/usage.md +23 -2
  167. package/package.json +1 -1
  168. package/src/__tests__/{TESTING_GUIDELINES.md → TEST_GUIDE_CURSOR.md} +20 -0
  169. package/src/__tests__/TEST_GUIDE_HUMAN.md +103 -0
  170. package/src/__tests__/fixtures/test-data.ts +90 -0
  171. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +260 -0
  172. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +224 -0
  173. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +273 -0
  174. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +98 -0
  175. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +436 -0
  176. package/src/__tests__/helpers/__tests__/timer-utils.test.ts +371 -0
  177. package/src/__tests__/helpers/component-test-utils.tsx +14 -4
  178. package/src/__tests__/helpers/optimized-test-setup.ts +68 -0
  179. package/src/__tests__/helpers/test-providers.tsx +329 -0
  180. package/src/__tests__/helpers/test-utils.tsx +91 -45
  181. package/src/__tests__/helpers/timer-utils.ts +71 -0
  182. package/src/__tests__/hooks/usePermissions.test.ts +1 -5
  183. package/src/__tests__/integration/UserProfile.test.tsx +1 -5
  184. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +42 -12
  185. package/src/__tests__/setup.ts +34 -28
  186. package/src/components/Alert/Alert.test.tsx +1 -5
  187. package/src/components/Avatar/Avatar.test.tsx +1 -5
  188. package/src/components/Button/Button.test.tsx +4 -20
  189. package/src/components/Card/Card.test.tsx +1 -5
  190. package/src/components/Checkbox/Checkbox.test.tsx +1 -5
  191. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -5
  192. package/src/components/DataTable/__tests__/DataTable.test.tsx +45 -49
  193. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +1 -5
  194. package/src/components/DataTable/__tests__/styles.test.ts +382 -0
  195. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +409 -0
  196. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +634 -0
  197. package/src/components/DataTable/core/__tests__/DataManager.test.ts +519 -0
  198. package/src/components/DataTable/core/__tests__/StateManager.test.ts +714 -0
  199. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +592 -0
  200. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +354 -0
  201. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +539 -0
  202. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +1 -5
  203. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +1 -8
  204. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +34 -38
  205. package/src/components/Footer/Footer.test.tsx +1 -5
  206. package/src/components/Form/Form.test.tsx +22 -35
  207. package/src/components/Header/Header.test.tsx +1 -9
  208. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +1 -5
  209. package/src/components/Input/Input.test.tsx +2 -10
  210. package/src/components/LoginForm/LoginForm.test.tsx +1 -5
  211. package/src/components/NavigationMenu/NavigationMenu.test.tsx +24 -24
  212. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +1 -6
  213. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -16
  214. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +1 -5
  215. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +1 -5
  216. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +1 -7
  217. package/src/components/PasswordReset/PasswordChangeForm.test.tsx +1 -9
  218. package/src/components/PasswordReset/PasswordResetForm.test.tsx +1 -9
  219. package/src/components/PublicLayout/PublicErrorBoundary.tsx +4 -5
  220. package/src/components/PublicLayout/PublicPageHeader.tsx +13 -9
  221. package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +666 -0
  222. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +457 -0
  223. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +393 -0
  224. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +351 -0
  225. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +374 -0
  226. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +388 -0
  227. package/src/components/Select/Select.bug-test.tsx +69 -0
  228. package/src/components/Select/Select.refactored.tsx +497 -0
  229. package/src/components/Select/Select.test.tsx +42 -49
  230. package/src/components/Select/Select.tsx +5 -2
  231. package/src/components/Select/hooks.ts +254 -0
  232. package/src/components/Switch/Switch.test.tsx +1 -5
  233. package/src/components/Table/__tests__/Table.test.tsx +775 -0
  234. package/src/components/Toast/Toast.test.tsx +15 -8
  235. package/src/components/Tooltip/Tooltip.test.tsx +1 -5
  236. package/src/components/UserMenu/UserMenu.test.tsx +3 -15
  237. package/src/components/__tests__/FileDisplay.test.tsx +575 -0
  238. package/src/components/__tests__/FileUpload.test.tsx +446 -0
  239. package/src/components/__tests__/SuperAdminGuard.test.tsx +422 -354
  240. package/src/hooks/__tests__/ServiceHooks.test.tsx +613 -0
  241. package/src/hooks/__tests__/hooks.integration.test.tsx +1 -10
  242. package/src/hooks/__tests__/useApiFetch.unit.test.ts +10 -14
  243. package/src/hooks/__tests__/useAppConfig.unit.test.ts +307 -0
  244. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +1 -6
  245. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +1 -5
  246. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +6 -9
  247. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +321 -0
  248. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +583 -0
  249. package/src/hooks/__tests__/usePublicEventLogo.unit.test.ts +640 -0
  250. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +435 -0
  251. package/src/hooks/__tests__/useRBAC.unit.test.ts +10 -10
  252. package/src/hooks/__tests__/useStorage.unit.test.ts +751 -0
  253. package/src/hooks/index.ts +3 -0
  254. package/src/hooks/public/usePublicEvent.ts +30 -9
  255. package/src/hooks/public/usePublicRouteParams.ts +13 -3
  256. package/src/hooks/services/useAuth.ts +50 -0
  257. package/src/hooks/services/useAuthService.ts +30 -0
  258. package/src/hooks/services/useCurrentEvent.ts +36 -0
  259. package/src/hooks/services/useCurrentOrganisation.ts +52 -0
  260. package/src/hooks/services/useEventService.ts +30 -0
  261. package/src/hooks/services/useInactivityService.ts +30 -0
  262. package/src/hooks/services/useOrganisationService.ts +30 -0
  263. package/src/hooks/services/usePermissions.ts +70 -0
  264. package/src/hooks/services/useRBACService.ts +30 -0
  265. package/src/hooks/useCounter.test.ts +1 -5
  266. package/src/hooks/useEventTheme.ts +86 -0
  267. package/src/hooks/useOrganisationPermissions.test.ts +2 -5
  268. package/src/hooks/useOrganisationSecurity.test.ts +1 -5
  269. package/src/hooks/usePermissionCache.test.ts +1 -5
  270. package/src/hooks/usePermissionCheck.ts +150 -0
  271. package/src/hooks/useSecureDataAccess.test.ts +1 -5
  272. package/src/index.ts +1 -0
  273. package/src/providers/OrganisationProvider.test.tsx +1 -5
  274. package/src/providers/OrganisationProvider.tsx +56 -4
  275. package/src/providers/UnifiedAuthProvider.test.tsx +1 -5
  276. package/src/providers/__tests__/AuthProvider.test.tsx +105 -439
  277. package/src/providers/__tests__/AuthProvider.test.tsx.backup +771 -0
  278. package/src/providers/__tests__/EventProvider.test.tsx +211 -110
  279. package/src/providers/__tests__/EventProvider.test.tsx.backup +824 -0
  280. package/src/providers/__tests__/InactivityProvider.test.tsx +1 -5
  281. package/src/providers/__tests__/OrganisationProvider.test.tsx +97 -261
  282. package/src/providers/__tests__/OrganisationProvider.test.tsx.backup +820 -0
  283. package/src/providers/__tests__/ServiceProviders.test.tsx +477 -0
  284. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +72 -504
  285. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup +911 -0
  286. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup2 +166 -0
  287. package/src/providers/services/AuthServiceProvider.tsx +65 -0
  288. package/src/providers/services/EventServiceProvider.tsx +83 -0
  289. package/src/providers/services/InactivityServiceProvider.tsx +83 -0
  290. package/src/providers/services/OrganisationServiceProvider.tsx +77 -0
  291. package/src/providers/services/RBACServiceProvider.tsx +79 -0
  292. package/src/providers/services/UnifiedAuthProvider.tsx +368 -0
  293. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +210 -0
  294. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +269 -0
  295. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +892 -0
  296. package/src/rbac/__tests__/engine.comprehensive.test.ts +954 -0
  297. package/src/rbac/__tests__/integration.authflow.test.tsx +1 -5
  298. package/src/rbac/__tests__/integration.navigation.test.tsx +1 -4
  299. package/src/rbac/__tests__/rbac-core.test.tsx +2 -7
  300. package/src/rbac/__tests__/rbac-functions.test.ts +1 -9
  301. package/src/rbac/__tests__/rbac-integration.test.ts +1 -9
  302. package/src/rbac/api.test.ts +1 -9
  303. package/src/rbac/cache.test.ts +10 -8
  304. package/src/rbac/cli/__tests__/policy-manager.test.ts +339 -0
  305. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +1 -5
  306. package/src/rbac/components/NavigationProvider.test.tsx +1 -5
  307. package/src/rbac/components/PagePermissionProvider.test.tsx +1 -5
  308. package/src/rbac/components/SecureDataProvider.test.tsx +1 -5
  309. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +25 -29
  310. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +27 -30
  311. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +23 -27
  312. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +18 -22
  313. package/src/rbac/config.test.ts +1 -5
  314. package/src/rbac/hooks/useCan.test.ts +262 -9
  315. package/src/rbac/hooks/usePermissions.test.ts +246 -6
  316. package/src/rbac/hooks/useRBAC.simple.test.ts +1 -5
  317. package/src/rbac/hooks/useRBAC.test.ts +472 -198
  318. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +1 -9
  319. package/src/services/AuthService.ts +416 -0
  320. package/src/services/EventService.ts +366 -0
  321. package/src/services/InactivityService.ts +388 -0
  322. package/src/services/OrganisationService.ts +592 -0
  323. package/src/services/RBACService.ts +522 -0
  324. package/src/services/__tests__/AuthService.test.ts +356 -0
  325. package/src/services/__tests__/BaseService.test.ts +314 -0
  326. package/src/services/__tests__/EventService.test.ts +489 -0
  327. package/src/services/__tests__/InactivityService.test.ts +403 -0
  328. package/src/services/__tests__/OrganisationService.test.ts +660 -0
  329. package/src/services/__tests__/RBACService.test.ts +492 -0
  330. package/src/services/base/BaseService.ts +87 -0
  331. package/src/services/interfaces/IAuthService.ts +39 -0
  332. package/src/services/interfaces/IEventService.ts +30 -0
  333. package/src/services/interfaces/IInactivityService.ts +31 -0
  334. package/src/services/interfaces/IOrganisationService.ts +41 -0
  335. package/src/services/interfaces/IRBACService.ts +62 -0
  336. package/src/theming/__tests__/runtime.test.ts +540 -0
  337. package/src/types/__tests__/file-reference.test.ts +447 -0
  338. package/src/types/__tests__/organisation.test.ts +1133 -0
  339. package/src/types/__tests__/theme.test.ts +830 -0
  340. package/src/types/__tests__/type-validation.test.ts +527 -0
  341. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +1 -5
  342. package/src/utils/__tests__/debugLogger.test.ts +417 -0
  343. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -6
  344. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -5
  345. package/src/utils/__tests__/lazyLoad.unit.test.tsx +35 -35
  346. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -5
  347. package/src/utils/__tests__/performanceBudgets.unit.test.ts +5 -11
  348. package/src/utils/__tests__/secureErrors.unit.test.ts +1 -6
  349. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -5
  350. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -5
  351. package/src/utils/__tests__/sessionTracking.unit.test.ts +1 -5
  352. package/src/utils/appIdResolver.test.ts +6 -10
  353. package/src/utils/appNameResolver.simple.test.ts +142 -0
  354. package/src/utils/appNameResolver.test.ts +31 -458
  355. package/src/utils/appNameResolver.test.ts.backup +494 -0
  356. package/src/utils/debugLogger.ts +26 -5
  357. package/src/utils/formatDate.test.ts +1 -5
  358. package/src/utils/organisationContext.test.ts +1 -5
  359. package/src/utils/performanceBudgets.ts +3 -4
  360. package/src/utils/secureDataAccess.test.ts +1 -5
  361. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -5
  362. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +1 -5
  363. package/dist/chunk-D7ARGIA3.js.map +0 -1
  364. package/dist/chunk-IPCH4YPT.js +0 -315
  365. package/dist/chunk-IPCH4YPT.js.map +0 -1
  366. package/dist/chunk-KRCRNXPD.js.map +0 -1
  367. package/dist/chunk-MOJXHWDE.js.map +0 -1
  368. package/dist/chunk-OPCWH3A4.js.map +0 -1
  369. package/dist/chunk-ZPG4XPV5.js.map +0 -1
  370. package/dist/chunk-ZPK5656W.js.map +0 -1
  371. package/docs/getting-started/installation.md +0 -269
  372. package/src/__tests__/REBUILD_PLAN.md +0 -223
  373. /package/dist/{DataTable-4IUY7BXB.js.map → DataTable-MPBSXUC6.js.map} +0 -0
  374. /package/dist/{chunk-PXWEDX7Y.js.map → chunk-2ARQW6VX.js.map} +0 -0
  375. /package/dist/{chunk-UYA6U6H7.js.map → chunk-Q2UP3ZWQ.js.map} +0 -0
@@ -0,0 +1,329 @@
1
+ /**
2
+ * @file Test Provider Utilities
3
+ * @package @jmruthers/pace-core
4
+ * @module TestHelpers
5
+ * @since 0.1.0
6
+ *
7
+ * Utilities for providing test contexts and mocking services in tests.
8
+ */
9
+
10
+ import React, { createContext, useContext } from 'react';
11
+ import { render, RenderOptions } from '@testing-library/react';
12
+ import { createMockSupabaseClient } from './supabaseMock';
13
+
14
+ // Mock context type
15
+ interface MockUnifiedAuthContextType {
16
+ // Auth state
17
+ user: any | null;
18
+ session: any | null;
19
+ isAuthenticated: boolean;
20
+ isLoading: boolean;
21
+ error: any | null;
22
+
23
+ // Auth methods
24
+ signIn: (email: string, password?: string) => Promise<{ error: any | null }>;
25
+ signUp: (email: string, password: string) => Promise<{ error: any | null }>;
26
+ signOut: () => Promise<{ error: any | null }>;
27
+ resetPassword: (email: string) => Promise<{ error: any | null }>;
28
+ updatePassword: (password: string) => Promise<{ error: any | null }>;
29
+ refreshSession: () => Promise<{ error: any | null }>;
30
+
31
+ // RBAC state
32
+ permissions: Record<string, boolean>;
33
+ roles: string[];
34
+ accessLevel: any;
35
+ appConfig: any | null;
36
+ selectedEventId: string | null;
37
+ userEventAccess: any[];
38
+ eventAccessLoading: boolean;
39
+ selectedOrganisationId: string | null;
40
+
41
+ // RBAC methods
42
+ hasPermission: (permission: string, orgId?: string) => boolean;
43
+ hasAnyPermission: (permissions: string[], orgId?: string) => boolean;
44
+ hasAllPermissions: (permissions: string[], orgId?: string) => boolean;
45
+ hasRole: (role: string) => boolean;
46
+ hasAccessLevel: (level: any) => boolean;
47
+ canAccess: (resource: string, action: string, orgId?: string) => boolean;
48
+ validatePermission: (permission: string, orgId?: string) => Promise<boolean>;
49
+ validateAccess: (resource: string, action: string, orgId?: string) => Promise<boolean>;
50
+ refreshPermissions: (eventId?: string, orgId?: string) => Promise<void>;
51
+ setSelectedEventId: (eventId: string | null) => void;
52
+ loadUserEventAccess: (orgId?: string) => Promise<void>;
53
+ getUserEventAccess: () => any[];
54
+ getUserEventAccessById: (eventId: string) => any | undefined;
55
+ requireOrganisationContext: () => string;
56
+
57
+ // Organisation state
58
+ organisations: any[];
59
+ selectedOrganisation: any | null;
60
+ organisationLoading: boolean;
61
+ organisationError: any | null;
62
+
63
+ // Organisation methods
64
+ loadUserOrganisations: () => Promise<void>;
65
+ selectOrganisation: (orgId: string) => void;
66
+ validateOrganisationAccess: (orgId: string) => Promise<boolean>;
67
+ getUserRole: (orgId?: string) => string;
68
+ ensureOrganisationContext: () => Promise<void>;
69
+ switchOrganisation: (orgId: string) => Promise<void>;
70
+
71
+ // Event state
72
+ events: any[];
73
+ selectedEvent: any | null;
74
+ eventLoading: boolean;
75
+ eventError: any | null;
76
+
77
+ // Event methods
78
+ loadUserEvents: () => Promise<void>;
79
+ selectEvent: (eventId: string) => void;
80
+ refreshEvents: () => Promise<void>;
81
+ createEvent: (eventData: any) => Promise<any>;
82
+ updateEvent: (eventId: string, eventData: any) => Promise<any>;
83
+ deleteEvent: (eventId: string) => Promise<void>;
84
+
85
+ // Inactivity state
86
+ isTracking: boolean;
87
+ timeRemaining: number;
88
+ showInactivityWarning: boolean;
89
+ inactivityLoading: boolean;
90
+ inactivityError: any | null;
91
+
92
+ // Inactivity methods
93
+ startTracking: () => void;
94
+ stopTracking: () => void;
95
+ resetTimer: () => void;
96
+ setShowInactivityWarning: (show: boolean) => void;
97
+ handleUserActivity: () => void;
98
+
99
+ // Dependencies
100
+ supabase: any;
101
+ appName: string;
102
+ }
103
+
104
+ // Mock Supabase client for tests
105
+ const mockSupabaseClient = createMockSupabaseClient();
106
+
107
+ // Default mock auth state
108
+ const defaultMockAuth: MockUnifiedAuthContextType = {
109
+ // Auth state
110
+ user: {
111
+ id: 'test-user-id',
112
+ email: 'test@example.com',
113
+ user_metadata: {},
114
+ app_metadata: {},
115
+ aud: 'authenticated',
116
+ created_at: '2023-01-01T00:00:00Z',
117
+ updated_at: '2023-01-01T00:00:00Z'
118
+ },
119
+ session: {
120
+ access_token: 'test-access-token',
121
+ refresh_token: 'test-refresh-token',
122
+ expires_in: 3600,
123
+ expires_at: Date.now() + 3600000,
124
+ token_type: 'bearer',
125
+ user: {
126
+ id: 'test-user-id',
127
+ email: 'test@example.com',
128
+ user_metadata: {},
129
+ app_metadata: {},
130
+ aud: 'authenticated',
131
+ created_at: '2023-01-01T00:00:00Z',
132
+ updated_at: '2023-01-01T00:00:00Z'
133
+ }
134
+ },
135
+ isAuthenticated: true,
136
+ isLoading: false,
137
+ error: null,
138
+
139
+ // Auth methods
140
+ signIn: vi.fn(() => Promise.resolve({ error: null })),
141
+ signOut: vi.fn(() => Promise.resolve({ error: null })),
142
+ signUp: vi.fn(() => Promise.resolve({ error: null })),
143
+ resetPassword: vi.fn(() => Promise.resolve({ error: null })),
144
+ updatePassword: vi.fn(() => Promise.resolve({ error: null })),
145
+ refreshSession: vi.fn(() => Promise.resolve({ error: null })),
146
+
147
+ // RBAC state
148
+ permissions: {},
149
+ roles: ['user'],
150
+ accessLevel: 'read',
151
+ appConfig: {
152
+ supports_direct_access: true,
153
+ requires_event: false
154
+ },
155
+ selectedEventId: null,
156
+ userEventAccess: [],
157
+ eventAccessLoading: false,
158
+ selectedOrganisationId: 'test-org-id',
159
+
160
+ // RBAC methods
161
+ hasPermission: vi.fn(() => true),
162
+ hasAnyPermission: vi.fn(() => true),
163
+ hasAllPermissions: vi.fn(() => true),
164
+ hasRole: vi.fn(() => true),
165
+ hasAccessLevel: vi.fn(() => true),
166
+ canAccess: vi.fn(() => true),
167
+ validatePermission: vi.fn(() => Promise.resolve(true)),
168
+ validateAccess: vi.fn(() => Promise.resolve(true)),
169
+ refreshPermissions: vi.fn(() => Promise.resolve()),
170
+ setSelectedEventId: vi.fn(),
171
+ loadUserEventAccess: vi.fn(() => Promise.resolve()),
172
+ getUserEventAccess: vi.fn(() => []),
173
+ getUserEventAccessById: vi.fn(() => undefined),
174
+ requireOrganisationContext: vi.fn(() => 'test-org-id'),
175
+
176
+ // Organisation state
177
+ organisations: [
178
+ {
179
+ id: 'test-org-id',
180
+ name: 'Test Organisation',
181
+ slug: 'test-org',
182
+ created_at: '2023-01-01T00:00:00Z',
183
+ updated_at: '2023-01-01T00:00:00Z'
184
+ }
185
+ ],
186
+ selectedOrganisation: {
187
+ id: 'test-org-id',
188
+ name: 'Test Organisation',
189
+ slug: 'test-org',
190
+ created_at: '2023-01-01T00:00:00Z',
191
+ updated_at: '2023-01-01T00:00:00Z'
192
+ },
193
+ organisationLoading: false,
194
+ organisationError: null,
195
+
196
+ // Organisation methods
197
+ loadUserOrganisations: vi.fn(() => Promise.resolve()),
198
+ selectOrganisation: vi.fn(),
199
+ validateOrganisationAccess: vi.fn(() => Promise.resolve(true)),
200
+ getUserRole: vi.fn(() => 'user'),
201
+ ensureOrganisationContext: vi.fn(() => Promise.resolve()),
202
+ switchOrganisation: vi.fn(() => Promise.resolve()),
203
+
204
+ // Event state
205
+ events: [
206
+ {
207
+ id: 'test-event-id',
208
+ name: 'Test Event',
209
+ description: 'Test event description',
210
+ start_date: '2023-01-01T00:00:00Z',
211
+ end_date: '2023-01-02T00:00:00Z',
212
+ status: 'active',
213
+ organisation_id: 'test-org-id',
214
+ created_at: '2023-01-01T00:00:00Z',
215
+ updated_at: '2023-01-01T00:00:00Z'
216
+ }
217
+ ],
218
+ selectedEvent: {
219
+ id: 'test-event-id',
220
+ name: 'Test Event',
221
+ description: 'Test event description',
222
+ start_date: '2023-01-01T00:00:00Z',
223
+ end_date: '2023-01-02T00:00:00Z',
224
+ status: 'active',
225
+ organisation_id: 'test-org-id',
226
+ created_at: '2023-01-01T00:00:00Z',
227
+ updated_at: '2023-01-01T00:00:00Z'
228
+ },
229
+ eventLoading: false,
230
+ eventError: null,
231
+
232
+ // Event methods
233
+ loadUserEvents: vi.fn(() => Promise.resolve()),
234
+ selectEvent: vi.fn(),
235
+ refreshEvents: vi.fn(() => Promise.resolve()),
236
+ createEvent: vi.fn(() => Promise.resolve()),
237
+ updateEvent: vi.fn(() => Promise.resolve()),
238
+ deleteEvent: vi.fn(() => Promise.resolve()),
239
+
240
+ // Inactivity state
241
+ isTracking: true,
242
+ timeRemaining: 300000, // 5 minutes
243
+ showInactivityWarning: false,
244
+ inactivityLoading: false,
245
+ inactivityError: null,
246
+
247
+ // Inactivity methods
248
+ startTracking: vi.fn(),
249
+ stopTracking: vi.fn(),
250
+ resetTimer: vi.fn(),
251
+ setShowInactivityWarning: vi.fn(),
252
+ handleUserActivity: vi.fn(),
253
+
254
+ // Dependencies
255
+ supabase: mockSupabaseClient,
256
+ appName: 'TEST'
257
+ };
258
+
259
+ // Create mock context
260
+ const MockUnifiedAuthContext = createContext<MockUnifiedAuthContextType | undefined>(undefined);
261
+
262
+ // Mock hook that matches the real useUnifiedAuth interface
263
+ export const useUnifiedAuth = () => {
264
+ const context = useContext(MockUnifiedAuthContext);
265
+ if (!context) {
266
+ throw new Error('useUnifiedAuth must be used within a TestProviderWrapper');
267
+ }
268
+ return context;
269
+ };
270
+
271
+ // Test provider wrapper component
272
+ interface TestProviderWrapperProps {
273
+ children: React.ReactNode;
274
+ mockAuth?: Partial<MockUnifiedAuthContextType>;
275
+ }
276
+
277
+ export function TestProviderWrapper({
278
+ children,
279
+ mockAuth = {}
280
+ }: TestProviderWrapperProps) {
281
+ const contextValue = {
282
+ ...defaultMockAuth,
283
+ ...mockAuth
284
+ };
285
+
286
+ return (
287
+ <MockUnifiedAuthContext.Provider value={contextValue}>
288
+ {children}
289
+ </MockUnifiedAuthContext.Provider>
290
+ );
291
+ }
292
+
293
+ // Custom render function with provider wrapper
294
+ interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
295
+ mockAuth?: Partial<MockUnifiedAuthContextType>;
296
+ }
297
+
298
+ export function renderWithProviders(
299
+ ui: React.ReactElement,
300
+ options: CustomRenderOptions = {}
301
+ ) {
302
+ const {
303
+ mockAuth = {},
304
+ ...renderOptions
305
+ } = options;
306
+
307
+ const Wrapper = ({ children }: { children: React.ReactNode }) => (
308
+ <TestProviderWrapper mockAuth={mockAuth}>
309
+ {children}
310
+ </TestProviderWrapper>
311
+ );
312
+
313
+ return render(ui, { wrapper: Wrapper, ...renderOptions });
314
+ }
315
+
316
+ // Mock hook utilities
317
+ export function createMockUseUnifiedAuth(overrides: Partial<MockUnifiedAuthContextType> = {}) {
318
+ return {
319
+ ...defaultMockAuth,
320
+ ...overrides
321
+ };
322
+ }
323
+
324
+ // Export default mock auth for easy access
325
+ export { defaultMockAuth };
326
+
327
+ // Re-export everything a test might need
328
+ export * from '@testing-library/react';
329
+ export { renderWithProviders as render };
@@ -9,19 +9,26 @@ import userEvent from '@testing-library/user-event';
9
9
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
10
10
  import { vi } from 'vitest';
11
11
 
12
- // Mock providers for testing
13
- const createTestQueryClient = () =>
14
- new QueryClient({
15
- defaultOptions: {
16
- queries: {
17
- retry: false,
18
- gcTime: 0,
19
- },
20
- mutations: {
21
- retry: false,
12
+ // Mock providers for testing - optimized for performance
13
+ let sharedQueryClient: QueryClient | null = null;
14
+
15
+ const createTestQueryClient = () => {
16
+ if (!sharedQueryClient) {
17
+ sharedQueryClient = new QueryClient({
18
+ defaultOptions: {
19
+ queries: {
20
+ retry: false,
21
+ gcTime: 0,
22
+ staleTime: Infinity, // Prevent unnecessary refetches
23
+ },
24
+ mutations: {
25
+ retry: false,
26
+ },
22
27
  },
23
- },
24
- });
28
+ });
29
+ }
30
+ return sharedQueryClient;
31
+ };
25
32
 
26
33
  // Custom render function with providers
27
34
  interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
@@ -57,36 +64,28 @@ export function renderWithProviders(
57
64
  export * from '@testing-library/react';
58
65
  export { userEvent };
59
66
 
60
- // Mock data generators
67
+ // Import shared fixtures for better performance
68
+ import { TEST_FIXTURES, createFixture } from '../fixtures/test-data';
69
+
70
+ // Optimized mock data generators using shared fixtures
61
71
  export const mockData = {
62
- user: (overrides = {}) => ({
63
- id: '1',
64
- email: 'test@example.com',
65
- name: 'Test User',
66
- ...overrides,
67
- }),
72
+ user: (overrides = {}) => createFixture(TEST_FIXTURES.users.basic, overrides),
68
73
 
69
74
  button: (overrides = {}) => ({
70
75
  children: 'Click me',
71
- onClick: vi.fn(),
76
+ onClick: TEST_FIXTURES.mockFunctions.onClick,
72
77
  ...overrides,
73
78
  }),
74
79
 
75
80
  form: (overrides = {}) => ({
76
- onSubmit: vi.fn(),
81
+ onSubmit: TEST_FIXTURES.mockFunctions.onSubmit,
77
82
  ...overrides,
78
83
  }),
79
84
  };
80
85
 
81
- // Test data generators for various data types
86
+ // Optimized test data generators using shared fixtures
82
87
  export const testDataGenerators = {
83
- user: (overrides = {}) => ({
84
- id: 'test-user-id',
85
- email: 'test@example.com',
86
- name: 'Test User',
87
- created_at: '2023-01-01T00:00:00Z',
88
- ...overrides,
89
- }),
88
+ user: (overrides = {}) => createFixture(TEST_FIXTURES.users.basic, overrides),
90
89
 
91
90
  createUser: (count = 1, overrides = {}) => {
92
91
  if (count === 1) {
@@ -184,33 +183,45 @@ export const testDataGenerators = {
184
183
  };
185
184
 
186
185
  // Mock Supabase client
187
- export const createMockSupabaseClient = () => {
188
- const mockRpc = vi.fn(() => Promise.resolve({ data: null, error: null }));
189
-
190
- // Create a chainable mock for the query builder
191
- const createQueryBuilder = () => {
192
- const queryBuilder = {
193
- select: vi.fn(() => queryBuilder),
194
- eq: vi.fn(() => queryBuilder),
186
+ // Optimized Supabase mock with shared instances
187
+ let sharedQueryBuilder: any = null;
188
+ let sharedAuthMock: any = null;
189
+
190
+ const createQueryBuilder = () => {
191
+ if (!sharedQueryBuilder) {
192
+ sharedQueryBuilder = {
193
+ select: vi.fn(() => sharedQueryBuilder),
194
+ eq: vi.fn(() => sharedQueryBuilder),
195
195
  single: vi.fn(() => Promise.resolve({ data: { id: 'test-app-id' }, error: null })),
196
196
  maybeSingle: vi.fn(() => Promise.resolve({ data: null, error: null })),
197
- order: vi.fn(() => queryBuilder),
197
+ order: vi.fn(() => sharedQueryBuilder),
198
198
  limit: vi.fn(() => Promise.resolve({ data: [], error: null })),
199
199
  insert: vi.fn(() => Promise.resolve({ data: null, error: null })),
200
200
  update: vi.fn(() => Promise.resolve({ data: null, error: null })),
201
201
  delete: vi.fn(() => Promise.resolve({ data: null, error: null })),
202
202
  };
203
- return queryBuilder;
204
- };
205
-
206
- return {
207
- from: vi.fn(() => createQueryBuilder()),
208
- auth: {
203
+ }
204
+ return sharedQueryBuilder;
205
+ };
206
+
207
+ const createAuthMock = () => {
208
+ if (!sharedAuthMock) {
209
+ sharedAuthMock = {
209
210
  getUser: vi.fn(() => Promise.resolve({ data: { user: null }, error: null })),
210
211
  getSession: vi.fn(() => Promise.resolve({ data: { session: null }, error: null })),
211
212
  signIn: vi.fn(() => Promise.resolve({ data: null, error: null })),
212
213
  signOut: vi.fn(() => Promise.resolve({ data: null, error: null })),
213
- },
214
+ };
215
+ }
216
+ return sharedAuthMock;
217
+ };
218
+
219
+ export const createMockSupabaseClient = () => {
220
+ const mockRpc = vi.fn(() => Promise.resolve({ data: null, error: null }));
221
+
222
+ return {
223
+ from: vi.fn(() => createQueryBuilder()),
224
+ auth: createAuthMock(),
214
225
  rpc: mockRpc,
215
226
  };
216
227
  };
@@ -261,3 +272,38 @@ export const testHelpers = {
261
272
  });
262
273
  },
263
274
  };
275
+
276
+ // Standard test setup utilities
277
+ export const setupTest = () => {
278
+ beforeEach(() => {
279
+ vi.clearAllMocks();
280
+ });
281
+
282
+ afterEach(() => {
283
+ vi.restoreAllMocks();
284
+ });
285
+ };
286
+
287
+ // Standard describe block structure for components
288
+ export const createComponentTestStructure = (componentName: string) => {
289
+ return {
290
+ describe: (testFn: () => void) => {
291
+ describe(componentName, () => {
292
+ setupTest();
293
+ testFn();
294
+ });
295
+ },
296
+ };
297
+ };
298
+
299
+ // Standard describe block structure for hooks
300
+ export const createHookTestStructure = (hookName: string) => {
301
+ return {
302
+ describe: (testFn: () => void) => {
303
+ describe(hookName, () => {
304
+ setupTest();
305
+ testFn();
306
+ });
307
+ },
308
+ };
309
+ };
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @file Timer Utilities for Tests
3
+ * @description Optimized utilities for time-dependent tests
4
+ */
5
+
6
+ import { vi } from 'vitest';
7
+
8
+ /**
9
+ * Fast-forward time for tests that use delays/timeouts
10
+ * This is much faster than waiting for real time
11
+ */
12
+ export const fastForwardTime = (ms: number) => {
13
+ vi.advanceTimersByTime(ms);
14
+ };
15
+
16
+ /**
17
+ * Fast-forward to the next timer
18
+ */
19
+ export const fastForwardToNextTimer = () => {
20
+ // Advance time to trigger the next scheduled timer
21
+ // We advance by a reasonable amount (1000ms) to trigger the next pending timer
22
+ vi.advanceTimersByTime(1000);
23
+ };
24
+
25
+ /**
26
+ * Run all pending timers
27
+ */
28
+ export const runAllTimers = () => {
29
+ // Advance time to trigger all pending one-shot timers
30
+ // Note: This does NOT run intervals to avoid infinite loops
31
+ vi.advanceTimersByTime(1000000);
32
+ };
33
+
34
+ /**
35
+ * Mock setTimeout to return immediately for faster tests
36
+ */
37
+ export const mockImmediateTimeout = () => {
38
+ vi.spyOn(global, 'setTimeout').mockImplementation((callback: Function) => {
39
+ callback();
40
+ return 1 as any;
41
+ });
42
+ };
43
+
44
+ /**
45
+ * Mock setInterval to return immediately for faster tests
46
+ */
47
+ export const mockImmediateInterval = () => {
48
+ vi.spyOn(global, 'setInterval').mockImplementation((callback: Function) => {
49
+ callback();
50
+ return 1 as any;
51
+ });
52
+ };
53
+
54
+ /**
55
+ * Setup optimized timers for a test
56
+ */
57
+ export const setupFastTimers = () => {
58
+ vi.useFakeTimers();
59
+ mockImmediateTimeout();
60
+ mockImmediateInterval();
61
+ };
62
+
63
+ /**
64
+ * Cleanup timers after test
65
+ */
66
+ export const cleanupTimers = () => {
67
+ // Use real timers first to ensure setTimeout/setInterval are available
68
+ // Then restore mocks to clean up any spy implementations
69
+ vi.useRealTimers();
70
+ vi.restoreAllMocks();
71
+ };
@@ -35,11 +35,7 @@ describe('usePermissions Hook Stability', () => {
35
35
  appId: 'app-123'
36
36
  };
37
37
 
38
- beforeEach(() => {
39
- vi.clearAllMocks();
40
- });
41
-
42
- describe('usePermissions', () => {
38
+ describe('usePermissions', () => {
43
39
  it('should return stable references when data hasn\'t changed', async () => {
44
40
  const mockPermissions = {
45
41
  'read:users': true,
@@ -53,11 +53,7 @@ const UserProfile = ({ userId }: { userId: string }) => {
53
53
  };
54
54
 
55
55
  describe('User Profile Integration Tests', () => {
56
- beforeEach(() => {
57
- vi.clearAllMocks();
58
- });
59
-
60
- describe('Data Loading', () => {
56
+ describe('Data Loading', () => {
61
57
  it('loads and displays user data', async () => {
62
58
  renderWithProviders(<UserProfile userId="1" />);
63
59