@jmruthers/pace-core 0.5.53 → 0.5.55

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 (398) hide show
  1. package/README.md +0 -4
  2. package/dist/{DataTable-7FMFXA7A.js → DataTable-4T627QFJ.js} +11 -11
  3. package/dist/{PublicLoadingSpinner-Bq_-BeK-.d.ts → PublicLoadingSpinner-SL8WaQN7.d.ts} +2 -21
  4. package/dist/{api-H5A3H4IR.js → api-LUNF5O6M.js} +3 -3
  5. package/dist/{appConfig-BVGyuvI7.d.ts → appConfig-DjpeG6P-.d.ts} +9 -1
  6. package/dist/{appNameResolver-7GHF5ED2.js → appNameResolver-UURKN7NF.js} +2 -2
  7. package/dist/{audit-BUW3LMJB.js → audit-6TOCAMKO.js} +2 -2
  8. package/dist/{chunk-MZBUOP4P.js → chunk-5BSLGBYI.js} +4 -3
  9. package/dist/chunk-5BSLGBYI.js.map +1 -0
  10. package/dist/{chunk-I5Z3QH5X.js → chunk-66C4BSAY.js} +2 -2
  11. package/dist/{chunk-I5Z3QH5X.js.map → chunk-66C4BSAY.js.map} +1 -1
  12. package/dist/{chunk-MYP2EGHX.js → chunk-AJ2KMES7.js} +21 -14
  13. package/dist/chunk-AJ2KMES7.js.map +1 -0
  14. package/dist/{chunk-EL2O4IUX.js → chunk-AQFRLC7K.js} +16 -24
  15. package/dist/{chunk-EL2O4IUX.js.map → chunk-AQFRLC7K.js.map} +1 -1
  16. package/dist/{chunk-7BNPOCLL.js → chunk-B2WTCLCV.js} +6 -2
  17. package/dist/chunk-B2WTCLCV.js.map +1 -0
  18. package/dist/{chunk-WJARTBCT.js → chunk-D7ARGIA3.js} +16 -7
  19. package/dist/chunk-D7ARGIA3.js.map +1 -0
  20. package/dist/{chunk-NRK4AIHQ.js → chunk-KBRACSJI.js} +3 -3
  21. package/dist/{chunk-NYUJ4FJR.js → chunk-KJDPSM64.js} +7 -7
  22. package/dist/chunk-KJDPSM64.js.map +1 -0
  23. package/dist/{chunk-GWSBHC4J.js → chunk-KLPVOPRI.js} +261 -38
  24. package/dist/chunk-KLPVOPRI.js.map +1 -0
  25. package/dist/{chunk-TRIZ7IB7.js → chunk-MPQDF75X.js} +148 -288
  26. package/dist/chunk-MPQDF75X.js.map +1 -0
  27. package/dist/{chunk-MSFACPQQ.js → chunk-PAEM3OWN.js} +11 -11
  28. package/dist/{chunk-MSFACPQQ.js.map → chunk-PAEM3OWN.js.map} +1 -1
  29. package/dist/{chunk-GIO7BFE7.js → chunk-RQD3D2CO.js} +66 -169
  30. package/dist/{chunk-GIO7BFE7.js.map → chunk-RQD3D2CO.js.map} +1 -1
  31. package/dist/{chunk-YDJW5XTN.js → chunk-STT7INZR.js} +25 -1
  32. package/dist/chunk-STT7INZR.js.map +1 -0
  33. package/dist/{chunk-6MTY77WU.js → chunk-TNMXZLDR.js} +3 -3
  34. package/dist/{chunk-BC3S53OZ.js → chunk-UQE2Y64H.js} +30 -14
  35. package/dist/chunk-UQE2Y64H.js.map +1 -0
  36. package/dist/{chunk-22KLBHPS.js → chunk-W66AZIOH.js} +2 -2
  37. package/dist/chunk-W66AZIOH.js.map +1 -0
  38. package/dist/{chunk-SS3E6QLB.js → chunk-YNUBMSMV.js} +2 -2
  39. package/dist/chunk-YNUBMSMV.js.map +1 -0
  40. package/dist/{chunk-NZ655MWE.js → chunk-ZOD2ZY6X.js} +5 -4
  41. package/dist/chunk-ZOD2ZY6X.js.map +1 -0
  42. package/dist/{chunk-74C6SNEC.js → chunk-ZPK5656W.js} +3 -3
  43. package/dist/{chunk-74C6SNEC.js.map → chunk-ZPK5656W.js.map} +1 -1
  44. package/dist/components.d.ts +22 -899
  45. package/dist/components.js +436 -3118
  46. package/dist/components.js.map +1 -1
  47. package/dist/file-reference-9xUOnwyt.d.ts +70 -0
  48. package/dist/hooks.d.ts +2 -2
  49. package/dist/hooks.js +10 -10
  50. package/dist/hooks.js.map +1 -1
  51. package/dist/index.d.ts +49 -9
  52. package/dist/index.js +190 -25
  53. package/dist/index.js.map +1 -1
  54. package/dist/{organisation-CO3Sh3_D.d.ts → organisation-t-vvQC3g.d.ts} +1 -8
  55. package/dist/providers.d.ts +2 -2
  56. package/dist/providers.js +5 -5
  57. package/dist/rbac/index.d.ts +65 -46
  58. package/dist/rbac/index.js +10 -12
  59. package/dist/styles/core.css +0 -125
  60. package/dist/types.d.ts +2 -1
  61. package/dist/types.js +3 -1
  62. package/dist/types.js.map +1 -1
  63. package/dist/{usePublicRouteParams-B2OcAsur.d.ts → usePublicRouteParams-CdoFxnJK.d.ts} +1 -1
  64. package/dist/utils.d.ts +3 -4
  65. package/dist/utils.js +44 -13
  66. package/dist/utils.js.map +1 -1
  67. package/docs/FILE_REFERENCE_SYSTEM.md +440 -0
  68. package/docs/INDEX.md +7 -5
  69. package/docs/README.md +0 -1
  70. package/docs/api/README.md +0 -4
  71. package/docs/api/classes/ErrorBoundary.md +1 -1
  72. package/docs/api/classes/InvalidScopeError.md +1 -1
  73. package/docs/api/classes/MissingUserContextError.md +1 -1
  74. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  75. package/docs/api/classes/PermissionDeniedError.md +2 -2
  76. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  77. package/docs/api/classes/RBACAuditManager.md +12 -12
  78. package/docs/api/classes/RBACCache.md +1 -1
  79. package/docs/api/classes/RBACEngine.md +6 -6
  80. package/docs/api/classes/RBACError.md +1 -1
  81. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  82. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  83. package/docs/api/classes/StorageUtils.md +281 -0
  84. package/docs/api/interfaces/AggregateConfig.md +1 -1
  85. package/docs/api/interfaces/ButtonProps.md +1 -1
  86. package/docs/api/interfaces/CardProps.md +1 -1
  87. package/docs/api/interfaces/ColorPalette.md +1 -1
  88. package/docs/api/interfaces/ColorShade.md +1 -1
  89. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  90. package/docs/api/interfaces/DataTableAction.md +1 -1
  91. package/docs/api/interfaces/DataTableColumn.md +1 -1
  92. package/docs/api/interfaces/DataTableProps.md +1 -1
  93. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  94. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  95. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  96. package/docs/api/interfaces/EventContextType.md +1 -1
  97. package/docs/api/interfaces/EventLogoProps.md +1 -1
  98. package/docs/api/interfaces/EventProviderProps.md +1 -1
  99. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  100. package/docs/api/interfaces/FileUploadProps.md +1 -1
  101. package/docs/api/interfaces/FooterProps.md +1 -1
  102. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  103. package/docs/api/interfaces/InputProps.md +1 -1
  104. package/docs/api/interfaces/LabelProps.md +1 -1
  105. package/docs/api/interfaces/LoginFormProps.md +1 -1
  106. package/docs/api/interfaces/NavigationAccessRecord.md +2 -2
  107. package/docs/api/interfaces/NavigationContextType.md +1 -1
  108. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  109. package/docs/api/interfaces/NavigationItem.md +1 -1
  110. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  111. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  112. package/docs/api/interfaces/Organisation.md +1 -1
  113. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  114. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  115. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  116. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  117. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  118. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  119. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  120. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  121. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  122. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  123. package/docs/api/interfaces/PaletteData.md +1 -1
  124. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  128. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  131. package/docs/api/interfaces/RBACConfig.md +1 -1
  132. package/docs/api/interfaces/RBACContextType.md +1 -1
  133. package/docs/api/interfaces/RBACLogger.md +1 -1
  134. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  135. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  136. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  137. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  138. package/docs/api/interfaces/RouteConfig.md +2 -2
  139. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  140. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  141. package/docs/api/interfaces/StorageConfig.md +1 -1
  142. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  143. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  144. package/docs/api/interfaces/StorageListOptions.md +1 -1
  145. package/docs/api/interfaces/StorageListResult.md +1 -1
  146. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  147. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  148. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  149. package/docs/api/interfaces/StyleImport.md +1 -1
  150. package/docs/api/interfaces/ToastActionElement.md +1 -1
  151. package/docs/api/interfaces/ToastProps.md +1 -1
  152. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  153. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  154. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  155. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  156. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  157. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  158. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  159. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  160. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  161. package/docs/api/interfaces/UserEventAccess.md +1 -1
  162. package/docs/api/interfaces/UserMenuProps.md +1 -1
  163. package/docs/api/interfaces/UserProfile.md +1 -1
  164. package/docs/api/modules.md +204 -200
  165. package/docs/api-reference/components.md +141 -163
  166. package/docs/api-reference/hooks.md +347 -0
  167. package/docs/core-concepts/rbac-system.md +69 -16
  168. package/docs/getting-started/examples/basic-auth-app.md +0 -1
  169. package/docs/implementation-guides/datatable-rbac-usage.md +12 -11
  170. package/docs/implementation-guides/file-upload-storage.md +733 -0
  171. package/docs/implementation-guides/inactivity-tracking.md +779 -0
  172. package/docs/implementation-guides/organisation-security.md +748 -0
  173. package/docs/implementation-guides/public-pages-advanced.md +1022 -0
  174. package/docs/migration/MIGRATION_GUIDE.md +684 -0
  175. package/docs/migration/README.md +13 -2
  176. package/docs/migration/rbac-migration.md +73 -0
  177. package/docs/rbac/examples/rbac-rls-integration-example.md +11 -13
  178. package/docs/style-guide.md +269 -1
  179. package/package.json +1 -1
  180. package/src/__tests__/TESTING_GUIDELINES.md +331 -18
  181. package/src/__tests__/helpers/supabaseMock.ts +99 -0
  182. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +10 -7
  183. package/src/__tests__/shared.ts +6 -0
  184. package/src/components/DataTable/components/ActionButtons.tsx +2 -2
  185. package/src/components/DataTable/components/DataTableCore.tsx +2 -2
  186. package/src/components/DataTable/components/UnifiedTableBody.tsx +1 -1
  187. package/src/components/DataTable/utils/debugTools.ts +2 -2
  188. package/src/components/Dialog/Dialog.test.tsx +12 -2
  189. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +6 -6
  190. package/src/components/ErrorBoundary/ErrorBoundary.tsx +2 -2
  191. package/src/components/FileDisplay.tsx +233 -0
  192. package/src/components/FileUpload.tsx +176 -0
  193. package/src/components/Footer/Footer.test.tsx +7 -7
  194. package/src/components/NavigationMenu/NavigationMenu.test.tsx +13 -6
  195. package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +30 -3
  196. package/src/components/OrganisationSelector/OrganisationSelector.tsx +1 -1
  197. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +558 -0
  198. package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
  199. package/src/components/PublicLayout/PublicPageDebugger.tsx +2 -2
  200. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +2 -2
  201. package/src/components/PublicLayout/PublicPageProvider.tsx +2 -2
  202. package/src/components/Select/Select.test.tsx +50 -15
  203. package/src/components/SuperAdminGuard.tsx +2 -2
  204. package/src/components/__tests__/SuperAdminGuard.test.tsx +559 -0
  205. package/src/components/index.ts +0 -183
  206. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +2 -2
  207. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +1 -1
  208. package/src/hooks/__tests__/useRBAC.unit.test.ts +191 -138
  209. package/src/hooks/public/usePublicEvent.ts +2 -2
  210. package/src/hooks/useAppConfig.ts +3 -3
  211. package/src/hooks/useComponentPerformance.ts +1 -1
  212. package/src/hooks/useDataTablePerformance.ts +1 -1
  213. package/src/hooks/useFileReference.ts +232 -0
  214. package/src/hooks/useOrganisationPermissions.test.ts +254 -344
  215. package/src/hooks/useOrganisationPermissions.ts +15 -7
  216. package/src/hooks/useOrganisationSecurity.test.ts +390 -402
  217. package/src/hooks/usePerformanceMonitor.ts +1 -1
  218. package/src/hooks/usePermissionCache.test.ts +264 -395
  219. package/src/hooks/usePermissionCache.ts +34 -4
  220. package/src/hooks/useSecureDataAccess.test.ts +486 -0
  221. package/src/hooks/useSecureDataAccess.ts +4 -1
  222. package/src/providers/InactivityProvider.tsx +2 -2
  223. package/src/providers/OrganisationProvider.test.simple.tsx +168 -0
  224. package/src/providers/OrganisationProvider.test.tsx +168 -0
  225. package/src/providers/OrganisationProvider.tsx +18 -31
  226. package/src/providers/UnifiedAuthProvider.test.simple.tsx +205 -0
  227. package/src/providers/UnifiedAuthProvider.test.tsx +128 -0
  228. package/src/providers/__tests__/InactivityProvider.test.tsx +3 -4
  229. package/src/providers/__tests__/OrganisationProvider.test.tsx +19 -14
  230. package/src/rbac/__tests__/integration.authflow.test.tsx +123 -0
  231. package/src/rbac/__tests__/integration.navigation.test.tsx +72 -0
  232. package/src/rbac/__tests__/integration.securedata.test.tsx +92 -0
  233. package/src/rbac/__tests__/integration.smoke.test.tsx +73 -0
  234. package/src/rbac/__tests__/rbac-core.test.tsx +26 -22
  235. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +411 -0
  236. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +285 -0
  237. package/src/rbac/__tests__/rbac-functions.test.ts +655 -0
  238. package/src/rbac/__tests__/rbac-integration.test.ts +532 -0
  239. package/src/rbac/__tests__/scenarios.user-role.test.tsx +196 -0
  240. package/src/rbac/api.test.ts +6 -6
  241. package/src/rbac/api.ts +2 -2
  242. package/src/rbac/audit.test.ts +485 -0
  243. package/src/rbac/audit.ts +7 -1
  244. package/src/rbac/cache-invalidation.ts +318 -0
  245. package/src/rbac/cache.test.ts +286 -0
  246. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +559 -0
  247. package/src/rbac/components/EnhancedNavigationMenu.tsx +29 -23
  248. package/src/rbac/components/NavigationProvider.test.tsx +449 -0
  249. package/src/rbac/components/PagePermissionGuard.tsx +4 -4
  250. package/src/rbac/components/PagePermissionProvider.test.tsx +479 -0
  251. package/src/rbac/components/SecureDataProvider.test.tsx +511 -0
  252. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +159 -430
  253. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +4 -5
  254. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +112 -118
  255. package/src/rbac/config.test.ts +410 -0
  256. package/src/rbac/engine.test.simple.ts +237 -0
  257. package/src/rbac/engine.test.ts +233 -0
  258. package/src/rbac/engine.ts +37 -41
  259. package/src/rbac/examples/CompleteRBACExample.tsx +3 -3
  260. package/src/rbac/examples/EventBasedApp.tsx +4 -4
  261. package/src/rbac/hooks/useRBAC.simple.test.ts +16 -0
  262. package/src/rbac/hooks/useRBAC.test.ts +207 -455
  263. package/src/rbac/hooks/useRBAC.ts +30 -22
  264. package/src/rbac/permissions.test.ts +128 -0
  265. package/src/rbac/permissions.ts +56 -141
  266. package/src/rbac/providers/RBACProvider.tsx +1 -1
  267. package/src/rbac/secureClient.test.ts +444 -0
  268. package/src/rbac/security.test.ts +390 -0
  269. package/src/rbac/security.ts +1 -1
  270. package/src/rbac/types.test.ts +382 -0
  271. package/src/rbac/types.ts +2 -2
  272. package/src/styles/base.css +208 -0
  273. package/src/styles/core.css +0 -125
  274. package/src/styles/semantic.css +24 -0
  275. package/src/types/file-reference.ts +77 -0
  276. package/src/types/rbac-functions.ts +290 -0
  277. package/src/types/supabase.ts +10 -28
  278. package/src/types/unified.ts +4 -1
  279. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +81 -55
  280. package/src/utils/__tests__/lazyLoad.unit.test.tsx +21 -12
  281. package/src/utils/__tests__/organisationContext.unit.test.ts +13 -7
  282. package/src/utils/__tests__/performanceBudgets.unit.test.ts +3 -3
  283. package/src/utils/__tests__/sessionTracking.unit.test.ts +32 -12
  284. package/src/utils/appConfig.ts +1 -1
  285. package/src/utils/appIdResolver.test.ts +503 -0
  286. package/src/utils/appIdResolver.ts +1 -1
  287. package/src/utils/appNameResolver.test.ts +494 -0
  288. package/src/utils/appNameResolver.ts +3 -2
  289. package/src/utils/bundleAnalysis.ts +3 -3
  290. package/src/utils/debugLogger.ts +1 -1
  291. package/src/utils/file-reference.ts +263 -0
  292. package/src/utils/formatDate.test.ts +2 -2
  293. package/src/utils/organisationContext.test.ts +340 -0
  294. package/src/utils/organisationContext.ts +19 -6
  295. package/src/utils/performanceBudgets.ts +2 -2
  296. package/src/utils/permissionUtils.test.ts +393 -0
  297. package/src/utils/permissionUtils.ts +5 -2
  298. package/src/utils/secureDataAccess.test.ts +715 -0
  299. package/src/utils/secureDataAccess.ts +21 -5
  300. package/src/utils/sessionTracking.ts +34 -4
  301. package/src/utils/storage/__tests__/helpers.unit.test.ts +328 -0
  302. package/src/utils/storage/__tests__/index.unit.test.ts +16 -0
  303. package/src/utils/storage/helpers.ts +20 -25
  304. package/src/utils/storage/index.ts +29 -1
  305. package/src/vite-env.d.ts +17 -0
  306. package/dist/chunk-22KLBHPS.js.map +0 -1
  307. package/dist/chunk-7BNPOCLL.js.map +0 -1
  308. package/dist/chunk-BC3S53OZ.js.map +0 -1
  309. package/dist/chunk-GWSBHC4J.js.map +0 -1
  310. package/dist/chunk-MYP2EGHX.js.map +0 -1
  311. package/dist/chunk-MZBUOP4P.js.map +0 -1
  312. package/dist/chunk-NYUJ4FJR.js.map +0 -1
  313. package/dist/chunk-NZ655MWE.js.map +0 -1
  314. package/dist/chunk-SS3E6QLB.js.map +0 -1
  315. package/dist/chunk-TRIZ7IB7.js.map +0 -1
  316. package/dist/chunk-WJARTBCT.js.map +0 -1
  317. package/dist/chunk-YDJW5XTN.js.map +0 -1
  318. package/docs/print-components/README.md +0 -258
  319. package/docs/print-components/api-reference.md +0 -636
  320. package/docs/print-components/examples/README.md +0 -204
  321. package/docs/print-components/examples/basic-report.tsx +0 -92
  322. package/docs/print-components/examples/card-catalog.tsx +0 -149
  323. package/docs/print-components/examples/cover-page-report.tsx +0 -163
  324. package/docs/print-components/quick-start.md +0 -363
  325. package/src/components/PrintButton/PrintButton.tsx +0 -321
  326. package/src/components/PrintButton/PrintButtonGroup.tsx +0 -84
  327. package/src/components/PrintButton/PrintToolbar.tsx +0 -94
  328. package/src/components/PrintButton/__tests__/PrintButton.test.tsx +0 -271
  329. package/src/components/PrintButton/examples/PrintButtonShowcase.tsx +0 -438
  330. package/src/components/PrintButton/index.ts +0 -33
  331. package/src/components/PrintButton/types.ts +0 -173
  332. package/src/components/PrintCard/PrintCard.tsx +0 -154
  333. package/src/components/PrintCard/PrintCardContent.tsx +0 -57
  334. package/src/components/PrintCard/PrintCardFooter.tsx +0 -60
  335. package/src/components/PrintCard/PrintCardGrid.tsx +0 -91
  336. package/src/components/PrintCard/PrintCardHeader.tsx +0 -78
  337. package/src/components/PrintCard/PrintCardImage.tsx +0 -81
  338. package/src/components/PrintCard/examples/PrintCardShowcase.tsx +0 -239
  339. package/src/components/PrintCard/index.ts +0 -34
  340. package/src/components/PrintCard/types.ts +0 -171
  341. package/src/components/PrintDataTable/PrintDataTable.tsx +0 -215
  342. package/src/components/PrintDataTable/PrintTableGroup.tsx +0 -90
  343. package/src/components/PrintDataTable/PrintTableRow.tsx +0 -76
  344. package/src/components/PrintDataTable/index.ts +0 -25
  345. package/src/components/PrintDataTable/types.ts +0 -67
  346. package/src/components/PrintFooter/PrintFooter.tsx +0 -183
  347. package/src/components/PrintFooter/PrintFooterContent.tsx +0 -71
  348. package/src/components/PrintFooter/PrintFooterInfo.tsx +0 -86
  349. package/src/components/PrintFooter/PrintPageNumber.tsx +0 -90
  350. package/src/components/PrintFooter/examples/PrintFooterShowcase.tsx +0 -390
  351. package/src/components/PrintFooter/index.ts +0 -30
  352. package/src/components/PrintFooter/types.ts +0 -149
  353. package/src/components/PrintGrid/PrintGrid.tsx +0 -180
  354. package/src/components/PrintGrid/PrintGridBreakpoint.tsx +0 -109
  355. package/src/components/PrintGrid/PrintGridContainer.tsx +0 -128
  356. package/src/components/PrintGrid/PrintGridItem.tsx +0 -220
  357. package/src/components/PrintGrid/examples/PrintGridShowcase.tsx +0 -359
  358. package/src/components/PrintGrid/index.ts +0 -31
  359. package/src/components/PrintGrid/types.ts +0 -159
  360. package/src/components/PrintHeader/PrintCoverHeader.tsx +0 -230
  361. package/src/components/PrintHeader/PrintHeader.tsx +0 -150
  362. package/src/components/PrintHeader/index.ts +0 -17
  363. package/src/components/PrintHeader/types.ts +0 -42
  364. package/src/components/PrintLayout/PrintLayout.tsx +0 -122
  365. package/src/components/PrintLayout/PrintLayoutContext.tsx +0 -66
  366. package/src/components/PrintLayout/PrintPageBreak.tsx +0 -52
  367. package/src/components/PrintLayout/examples/PrintShowcase.tsx +0 -230
  368. package/src/components/PrintLayout/index.ts +0 -19
  369. package/src/components/PrintLayout/types.ts +0 -37
  370. package/src/components/PrintPageBreak/PrintPageBreak.tsx +0 -120
  371. package/src/components/PrintPageBreak/PrintPageBreakGroup.tsx +0 -90
  372. package/src/components/PrintPageBreak/PrintPageBreakIndicator.tsx +0 -112
  373. package/src/components/PrintPageBreak/examples/PrintPageBreakShowcase.tsx +0 -279
  374. package/src/components/PrintPageBreak/index.ts +0 -23
  375. package/src/components/PrintPageBreak/types.ts +0 -94
  376. package/src/components/PrintSection/PrintColumn.tsx +0 -104
  377. package/src/components/PrintSection/PrintDivider.tsx +0 -101
  378. package/src/components/PrintSection/PrintSection.tsx +0 -129
  379. package/src/components/PrintSection/PrintSectionContent.tsx +0 -75
  380. package/src/components/PrintSection/PrintSectionHeader.tsx +0 -97
  381. package/src/components/PrintSection/examples/PrintSectionShowcase.tsx +0 -258
  382. package/src/components/PrintSection/index.ts +0 -33
  383. package/src/components/PrintSection/types.ts +0 -155
  384. package/src/components/PrintText/PrintText.tsx +0 -116
  385. package/src/components/PrintText/index.ts +0 -16
  386. package/src/components/PrintText/types.ts +0 -24
  387. package/src/rbac/__tests__/integration.test.tsx +0 -218
  388. package/src/utils/print/PrintDataProcessor.ts +0 -390
  389. package/src/utils/print/examples/PrintUtilitiesShowcase.tsx +0 -397
  390. package/src/utils/print/index.ts +0 -29
  391. package/src/utils/print/types.ts +0 -196
  392. package/src/utils/print/usePrintOptimization.ts +0 -272
  393. /package/dist/{DataTable-7FMFXA7A.js.map → DataTable-4T627QFJ.js.map} +0 -0
  394. /package/dist/{api-H5A3H4IR.js.map → api-LUNF5O6M.js.map} +0 -0
  395. /package/dist/{appNameResolver-7GHF5ED2.js.map → appNameResolver-UURKN7NF.js.map} +0 -0
  396. /package/dist/{audit-BUW3LMJB.js.map → audit-6TOCAMKO.js.map} +0 -0
  397. /package/dist/{chunk-NRK4AIHQ.js.map → chunk-KBRACSJI.js.map} +0 -0
  398. /package/dist/{chunk-6MTY77WU.js.map → chunk-TNMXZLDR.js.map} +0 -0
@@ -0,0 +1,128 @@
1
+ /**
2
+ * @file Simplified Unified Authentication Provider Tests
3
+ * @package @jmruthers/pace-core
4
+ * @module Providers/UnifiedAuthProvider
5
+ * @since 0.1.0
6
+ *
7
+ * Basic tests for the UnifiedAuthProvider component.
8
+ */
9
+
10
+ import { render, screen } from '@testing-library/react';
11
+ import { vi, describe, it, expect, beforeEach } from 'vitest';
12
+ import { ReactNode } from 'react';
13
+ import { UnifiedAuthProvider, useUnifiedAuth } from './UnifiedAuthProvider';
14
+
15
+ // Mock all the child providers with minimal implementations
16
+ vi.mock('./AuthProvider', () => ({
17
+ AuthProvider: ({ children }: { children: ReactNode }) => <div>{children}</div>,
18
+ useAuth: () => ({
19
+ user: { id: 'test-user', email: 'test@example.com' },
20
+ session: { access_token: 'test-token' },
21
+ authLoading: false,
22
+ authError: null,
23
+ signIn: vi.fn(),
24
+ signUp: vi.fn(),
25
+ signOut: vi.fn(),
26
+ resetPassword: vi.fn(),
27
+ isAuthenticated: true,
28
+ supabase: {}
29
+ })
30
+ }));
31
+
32
+ vi.mock('../rbac/providers/RBACProvider', () => ({
33
+ RBACProvider: ({ children }: { children: ReactNode }) => <div>{children}</div>,
34
+ useRBAC: () => ({
35
+ rbacLoading: false,
36
+ rbacError: null,
37
+ hasPermission: vi.fn().mockReturnValue(true),
38
+ hasRole: vi.fn().mockReturnValue(true),
39
+ hasAccessLevel: vi.fn().mockReturnValue(true),
40
+ validatePermission: vi.fn().mockResolvedValue(true),
41
+ canAccess: vi.fn().mockReturnValue(true),
42
+ getAccessLevel: vi.fn().mockReturnValue('admin'),
43
+ setSelectedEventId: vi.fn(),
44
+ permissions: { 'read:users': true },
45
+ roles: ['admin'],
46
+ accessLevel: 'admin',
47
+ selectedEventId: null,
48
+ appConfig: null,
49
+ userEventAccess: [],
50
+ eventAccessLoading: false,
51
+ selectedOrganisationId: 'org-123',
52
+ requireOrganisationContext: vi.fn().mockReturnValue('org-123'),
53
+ hasAnyPermission: vi.fn().mockReturnValue(true),
54
+ hasAllPermissions: vi.fn().mockReturnValue(true),
55
+ validateAccess: vi.fn().mockResolvedValue(true),
56
+ refreshPermissions: vi.fn().mockResolvedValue(undefined),
57
+ loadUserEventAccess: vi.fn().mockResolvedValue(undefined),
58
+ getUserEventAccess: vi.fn().mockReturnValue(undefined)
59
+ })
60
+ }));
61
+
62
+ vi.mock('./InactivityProvider', () => ({
63
+ InactivityProvider: ({ children }: { children: ReactNode }) => <div>{children}</div>,
64
+ useInactivity: () => ({
65
+ isIdle: false,
66
+ timeRemaining: 30 * 60 * 1000,
67
+ showWarning: false,
68
+ staySignedIn: vi.fn(),
69
+ signOutNow: vi.fn()
70
+ })
71
+ }));
72
+
73
+ // Mock Supabase client
74
+ const mockSupabase = {
75
+ auth: {
76
+ getUser: vi.fn().mockResolvedValue({ data: { user: null }, error: null }),
77
+ getSession: vi.fn().mockResolvedValue({ data: { session: null }, error: null }),
78
+ onAuthStateChange: vi.fn().mockReturnValue({ data: { subscription: { unsubscribe: vi.fn() } } })
79
+ }
80
+ };
81
+
82
+ describe('UnifiedAuthProvider', () => {
83
+ beforeEach(() => {
84
+ vi.clearAllMocks();
85
+ });
86
+
87
+ describe('Basic Functionality', () => {
88
+ it('renders without crashing', () => {
89
+ render(
90
+ <UnifiedAuthProvider supabaseClient={mockSupabase as any} appName="test-app">
91
+ <div data-testid="test-content">Test Content</div>
92
+ </UnifiedAuthProvider>
93
+ );
94
+
95
+ expect(screen.getByTestId('test-content')).toBeInTheDocument();
96
+ });
97
+
98
+ it('provides context without errors', () => {
99
+ const TestConsumer = () => {
100
+ const context = useUnifiedAuth();
101
+ // Just verify context exists without checking specific values
102
+ expect(context).toBeDefined();
103
+ return <div data-testid="context-consumer">Context Available</div>;
104
+ };
105
+
106
+ render(
107
+ <UnifiedAuthProvider supabaseClient={mockSupabase as any} appName="test-app">
108
+ <TestConsumer />
109
+ </UnifiedAuthProvider>
110
+ );
111
+
112
+ expect(screen.getByTestId('context-consumer')).toBeInTheDocument();
113
+ });
114
+
115
+ it('renders children correctly', () => {
116
+ render(
117
+ <UnifiedAuthProvider supabaseClient={mockSupabase as any} appName="test-app">
118
+ <div data-testid="child-1">Child 1</div>
119
+ <div data-testid="child-2">Child 2</div>
120
+ </UnifiedAuthProvider>
121
+ );
122
+
123
+ expect(screen.getByTestId('child-1')).toBeInTheDocument();
124
+ expect(screen.getByTestId('child-2')).toBeInTheDocument();
125
+ });
126
+ });
127
+
128
+ });
@@ -509,9 +509,8 @@ describe('InactivityProvider', () => {
509
509
  it('warns about disabling inactivity in production', () => {
510
510
  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
511
511
 
512
- // Mock production environment
513
- const originalEnv = process.env.NODE_ENV;
514
- process.env.NODE_ENV = 'production';
512
+ // Mock production environment using vi.stubEnv
513
+ vi.stubEnv('MODE', 'production');
515
514
 
516
515
  render(
517
516
  <TestWrapper dangerouslyDisableInactivity={true}>
@@ -524,7 +523,7 @@ describe('InactivityProvider', () => {
524
523
  );
525
524
 
526
525
  // Restore environment
527
- process.env.NODE_ENV = originalEnv;
526
+ vi.unstubAllEnvs();
528
527
  consoleErrorSpy.mockRestore();
529
528
  });
530
529
 
@@ -178,27 +178,32 @@ describe('OrganisationProvider', () => {
178
178
  // Create mock Supabase client
179
179
  mockSupabaseClient = createMockSupabaseClient();
180
180
  mockSupabaseClient.from = vi.fn((table: string) => {
181
- // Return different responses based on the table
182
- if (table === 'organisation_memberships') {
183
- return {
181
+ // Create a mock query builder that handles the chained calls
182
+ const createMockQueryBuilder = (data: any) => {
183
+ const queryBuilder = {
184
184
  select: vi.fn().mockReturnThis(),
185
185
  eq: vi.fn().mockReturnThis(),
186
186
  is: vi.fn().mockReturnThis(),
187
- in: vi.fn().mockResolvedValue({
188
- data: mockMemberships,
189
- error: null
187
+ in: vi.fn().mockReturnThis(),
188
+ order: vi.fn().mockReturnThis(),
189
+ limit: vi.fn().mockReturnThis(),
190
+ single: vi.fn().mockResolvedValue({ data: data[0] || null, error: null }),
191
+ maybeSingle: vi.fn().mockResolvedValue({ data: data[0] || null, error: null }),
192
+ // Make it thenable
193
+ then: vi.fn().mockImplementation((resolve) => {
194
+ resolve({ data, error: null });
190
195
  }),
191
196
  };
197
+ return queryBuilder;
198
+ };
199
+
200
+ // Return different responses based on the table
201
+ if (table === 'rbac_organisation_roles') {
202
+ return createMockQueryBuilder(mockMemberships);
192
203
  } else if (table === 'organisations') {
193
- return {
194
- select: vi.fn().mockReturnThis(),
195
- in: vi.fn().mockResolvedValue({
196
- data: mockOrganisations,
197
- error: null
198
- }),
199
- };
204
+ return createMockQueryBuilder(mockOrganisations);
200
205
  }
201
- return mockQueryBuilder;
206
+ return createMockQueryBuilder([]);
202
207
  });
203
208
 
204
209
  // Mock auth state
@@ -0,0 +1,123 @@
1
+ import React from 'react';
2
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
3
+ import { render, screen, waitFor } from '@testing-library/react';
4
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5
+ import { createMemoryRouter, RouterProvider } from 'react-router-dom';
6
+ import { UnifiedAuthProvider } from '../../providers/UnifiedAuthProvider';
7
+ import { OrganisationProvider } from '../../providers/OrganisationProvider';
8
+ import { RBACProvider } from '../providers/RBACProvider';
9
+ import { useRBAC } from '../hooks/useRBAC';
10
+ import type { SupabaseClient, User } from '@supabase/supabase-js';
11
+
12
+ const mockSupabaseClient = {
13
+ auth: {
14
+ getUser: vi.fn(),
15
+ },
16
+ } as unknown as SupabaseClient;
17
+
18
+ // Local lightweight mocks to avoid importing heavy RBAC modules during bisect
19
+ vi.mock('../hooks/useRBAC', () => ({
20
+ useRBAC: () => ({
21
+ user: { email: 'test@example.com' },
22
+ isAuthenticated: true,
23
+ isLoading: false,
24
+ }),
25
+ }));
26
+
27
+ vi.mock('../providers/RBACProvider', () => ({
28
+ RBACProvider: ({ children }: any) => children,
29
+ }));
30
+
31
+ const mockUser: User = {
32
+ id: 'user-123',
33
+ email: 'test@example.com',
34
+ created_at: '2023-01-01T00:00:00Z',
35
+ updated_at: '2023-01-01T00:00:00Z',
36
+ aud: 'authenticated',
37
+ role: 'authenticated',
38
+ app_metadata: {},
39
+ user_metadata: {},
40
+ identities: [],
41
+ factors: [],
42
+ } as User;
43
+
44
+ const MinimalAuthComponent = () => {
45
+ const { user, isAuthenticated, isLoading } = useRBAC();
46
+ if (isLoading) return <div>Loading...</div>;
47
+ if (!isAuthenticated) return <div>Not authenticated</div>;
48
+ return (
49
+ <div>
50
+ <h1>AuthFlow Minimal</h1>
51
+ <p>User: {user?.email}</p>
52
+ </div>
53
+ );
54
+ };
55
+
56
+ const Wrapper = ({ children }: { children: React.ReactNode }) => {
57
+ const queryClient = new QueryClient({
58
+ defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
59
+ });
60
+ return (
61
+ <QueryClientProvider client={queryClient}>
62
+ <UnifiedAuthProvider supabase={mockSupabaseClient}>
63
+ <OrganisationProvider>
64
+ <RBACProvider>{children}</RBACProvider>
65
+ </OrganisationProvider>
66
+ </UnifiedAuthProvider>
67
+ </QueryClientProvider>
68
+ );
69
+ };
70
+
71
+ describe('RBAC AuthFlow Minimal', () => {
72
+ beforeEach(() => {
73
+ vi.clearAllMocks();
74
+ mockSupabaseClient.auth.getUser = vi
75
+ .fn()
76
+ .mockResolvedValue({ data: { user: mockUser }, error: null });
77
+ });
78
+
79
+ afterEach(() => {
80
+ vi.restoreAllMocks();
81
+ });
82
+
83
+ it('renders authenticated view', async () => {
84
+ const router = createMemoryRouter([{ path: '/', element: <MinimalAuthComponent /> }]);
85
+
86
+ render(
87
+ <Wrapper>
88
+ <RouterProvider router={router} />
89
+ </Wrapper>
90
+ );
91
+
92
+ await waitFor(() => {
93
+ expect(screen.getByText('AuthFlow Minimal')).toBeInTheDocument();
94
+ });
95
+ expect(screen.getByText('User: test@example.com')).toBeInTheDocument();
96
+ });
97
+
98
+ it('renders not authenticated view', async () => {
99
+ const useRBACModule = await import('../hooks/useRBAC');
100
+ vi.spyOn(useRBACModule, 'useRBAC').mockReturnValue({
101
+ user: null,
102
+ isAuthenticated: false,
103
+ isLoading: false,
104
+ } as any);
105
+ mockSupabaseClient.auth.getUser = vi
106
+ .fn()
107
+ .mockResolvedValue({ data: { user: null }, error: null });
108
+
109
+ const router = createMemoryRouter([{ path: '/', element: <MinimalAuthComponent /> }]);
110
+
111
+ render(
112
+ <Wrapper>
113
+ <RouterProvider router={router} />
114
+ </Wrapper>
115
+ );
116
+
117
+ await waitFor(() => {
118
+ expect(screen.getByText('Not authenticated')).toBeInTheDocument();
119
+ });
120
+ });
121
+ });
122
+
123
+
@@ -0,0 +1,72 @@
1
+ import React from 'react';
2
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
3
+ import { render, screen, waitFor } from '@testing-library/react';
4
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5
+ import { createMemoryRouter, RouterProvider } from 'react-router-dom';
6
+ import { UnifiedAuthProvider } from '../../providers/UnifiedAuthProvider';
7
+ import { OrganisationProvider } from '../../providers/OrganisationProvider';
8
+ import { RBACProvider } from '../providers/RBACProvider';
9
+ import { NavigationProvider } from '../components/NavigationProvider';
10
+ import { EnhancedNavigationMenu } from '../components/EnhancedNavigationMenu';
11
+
12
+ // Local lightweight mocks
13
+ vi.mock('../components/EnhancedNavigationMenu', () => ({
14
+ EnhancedNavigationMenu: () => (
15
+ <div>
16
+ <div>Users</div>
17
+ <div>Settings</div>
18
+ <div>Admin</div>
19
+ </div>
20
+ ),
21
+ }));
22
+
23
+ const Wrapper = ({ children }: { children: React.ReactNode }) => {
24
+ const queryClient = new QueryClient({
25
+ defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
26
+ });
27
+ return (
28
+ <QueryClientProvider client={queryClient}>
29
+ <UnifiedAuthProvider supabase={{} as any}>
30
+ <OrganisationProvider>
31
+ <RBACProvider>{children}</RBACProvider>
32
+ </OrganisationProvider>
33
+ </UnifiedAuthProvider>
34
+ </QueryClientProvider>
35
+ );
36
+ };
37
+
38
+ const NavUnderTest = () => {
39
+ const navigationItems = [
40
+ { label: 'Users', path: '/users', permissions: ['read:users'] },
41
+ { label: 'Settings', path: '/settings', permissions: ['write:users'] },
42
+ { label: 'Admin', path: '/admin', permissions: ['delete:users'] },
43
+ ];
44
+ return (
45
+ <NavigationProvider navigationItems={navigationItems}>
46
+ <EnhancedNavigationMenu />
47
+ </NavigationProvider>
48
+ );
49
+ };
50
+
51
+ describe('RBAC Navigation Integration', () => {
52
+ beforeEach(() => {
53
+ vi.clearAllMocks();
54
+ });
55
+ afterEach(() => vi.restoreAllMocks());
56
+
57
+ it('shows all mocked navigation items', async () => {
58
+ const router = createMemoryRouter([{ path: '/', element: <NavUnderTest /> }]);
59
+ render(
60
+ <Wrapper>
61
+ <RouterProvider router={router} />
62
+ </Wrapper>
63
+ );
64
+ await waitFor(() => {
65
+ expect(screen.getByText('Users')).toBeInTheDocument();
66
+ expect(screen.getByText('Settings')).toBeInTheDocument();
67
+ expect(screen.getByText('Admin')).toBeInTheDocument();
68
+ });
69
+ });
70
+ });
71
+
72
+
@@ -0,0 +1,92 @@
1
+ import React from 'react';
2
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
3
+ import { render, screen, waitFor } from '@testing-library/react';
4
+ import userEvent from '@testing-library/user-event';
5
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
6
+ import { createMemoryRouter, RouterProvider } from 'react-router-dom';
7
+ import { UnifiedAuthProvider } from '../../providers/UnifiedAuthProvider';
8
+ import { OrganisationProvider } from '../../providers/OrganisationProvider';
9
+ import { RBACProvider } from '../providers/RBACProvider';
10
+ import { useSecureDataAccess } from '../../hooks/useSecureDataAccess';
11
+
12
+ // Local lightweight mock for secure data access
13
+ vi.mock('../../hooks/useSecureDataAccess', () => ({
14
+ useSecureDataAccess: () => ({
15
+ secureDataAccess: {
16
+ secureQuery: vi.fn().mockResolvedValue([
17
+ { id: '1', name: 'User 1', email: 'user1@example.com' },
18
+ { id: '2', name: 'User 2', email: 'user2@example.com' },
19
+ ]),
20
+ },
21
+ }),
22
+ }));
23
+
24
+ const Wrapper = ({ children }: { children: React.ReactNode }) => {
25
+ const queryClient = new QueryClient({
26
+ defaultOptions: { queries: { retry: false }, mutations: { retry: false } },
27
+ });
28
+ return (
29
+ <QueryClientProvider client={queryClient}>
30
+ <UnifiedAuthProvider supabase={{} as any}>
31
+ <OrganisationProvider>
32
+ <RBACProvider>{children}</RBACProvider>
33
+ </OrganisationProvider>
34
+ </UnifiedAuthProvider>
35
+ </QueryClientProvider>
36
+ );
37
+ };
38
+
39
+ const SecureDataProbe = () => {
40
+ const { secureDataAccess: secureData } = useSecureDataAccess();
41
+ const [data, setData] = React.useState<any[] | null>(null);
42
+ const [loading, setLoading] = React.useState(false);
43
+
44
+ const fetchData = async () => {
45
+ setLoading(true);
46
+ const result = await secureData.secureQuery({
47
+ table: 'users',
48
+ select: 'id, name, email',
49
+ organisationId: 'org-123',
50
+ });
51
+ setData(result);
52
+ setLoading(false);
53
+ };
54
+
55
+ return (
56
+ <div>
57
+ <button onClick={fetchData} disabled={loading}>
58
+ {loading ? 'Loading...' : 'Fetch Data'}
59
+ </button>
60
+ {data && (
61
+ <>
62
+ <div>{data[0]?.name}</div>
63
+ <div>{data[1]?.name}</div>
64
+ </>
65
+ )}
66
+ </div>
67
+ );
68
+ };
69
+
70
+ describe('RBAC Secure Data Integration', () => {
71
+ beforeEach(() => vi.clearAllMocks());
72
+ afterEach(() => vi.restoreAllMocks());
73
+
74
+ it('fetches data with organisation context via secureQuery', async () => {
75
+ const router = createMemoryRouter([{ path: '/', element: <SecureDataProbe /> }]);
76
+ render(
77
+ <Wrapper>
78
+ <RouterProvider router={router} />
79
+ </Wrapper>
80
+ );
81
+
82
+ const user = userEvent.setup();
83
+ await user.click(screen.getByText('Fetch Data'));
84
+
85
+ await waitFor(() => {
86
+ expect(screen.getByText('User 1')).toBeInTheDocument();
87
+ expect(screen.getByText('User 2')).toBeInTheDocument();
88
+ });
89
+ });
90
+ });
91
+
92
+
@@ -0,0 +1,73 @@
1
+ import React from 'react';
2
+ import { describe, it, expect, vi } from 'vitest';
3
+ import { render, screen } from '@testing-library/react';
4
+ import { UnifiedAuthProvider } from '../../providers/UnifiedAuthProvider';
5
+ import { OrganisationProvider } from '../../providers/OrganisationProvider';
6
+ import { RBACProvider } from '../providers/RBACProvider';
7
+ import { useCan } from '../hooks';
8
+
9
+ describe('RBAC Integration Smoke', () => {
10
+ it('renders trivial component without providers', () => {
11
+ render(<div>RBAC Smoke OK</div>);
12
+ expect(screen.getByText('RBAC Smoke OK')).toBeInTheDocument();
13
+ });
14
+
15
+ it('renders with UnifiedAuthProvider only', () => {
16
+ render(
17
+ <UnifiedAuthProvider supabase={{} as any}>
18
+ <div>Auth Only</div>
19
+ </UnifiedAuthProvider>
20
+ );
21
+ expect(screen.getByText('Auth Only')).toBeInTheDocument();
22
+ });
23
+
24
+ it('renders with OrganisationProvider only', () => {
25
+ render(
26
+ <OrganisationProvider>
27
+ <div>Org Only</div>
28
+ </OrganisationProvider>
29
+ );
30
+ expect(screen.getByText('Org Only')).toBeInTheDocument();
31
+ });
32
+
33
+ it('renders with RBACProvider only', () => {
34
+ render(
35
+ <RBACProvider>
36
+ <div>RBAC Only</div>
37
+ </RBACProvider>
38
+ );
39
+ expect(screen.getByText('RBAC Only')).toBeInTheDocument();
40
+ });
41
+
42
+ it('renders full minimal stack without RBAC hooks usage', () => {
43
+ render(
44
+ <UnifiedAuthProvider supabase={{} as any}>
45
+ <OrganisationProvider>
46
+ <RBACProvider>
47
+ <div>Full Stack Minimal</div>
48
+ </RBACProvider>
49
+ </OrganisationProvider>
50
+ </UnifiedAuthProvider>
51
+ );
52
+ expect(screen.getByText('Full Stack Minimal')).toBeInTheDocument();
53
+ });
54
+
55
+ it('mounts a component that calls useCan() (global mock) without leaking', () => {
56
+ const Probe = () => {
57
+ const { hasPermission } = useCan() as any;
58
+ return <div>{hasPermission('read:users') ? 'HasPerm' : 'NoPerm'}</div>;
59
+ };
60
+ render(
61
+ <UnifiedAuthProvider supabase={{} as any}>
62
+ <OrganisationProvider>
63
+ <RBACProvider>
64
+ <Probe />
65
+ </RBACProvider>
66
+ </OrganisationProvider>
67
+ </UnifiedAuthProvider>
68
+ );
69
+ expect(screen.getByText('HasPerm')).toBeInTheDocument();
70
+ });
71
+ });
72
+
73
+