@jmruthers/pace-core 0.5.68 → 0.5.70

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 (394) hide show
  1. package/dist/{DataTable-4IUY7BXB.js → DataTable-OSELOGMA.js} +6 -6
  2. package/dist/{PublicLoadingSpinner-DdKXTkCZ.d.ts → PublicLoadingSpinner-DLpF5bbs.d.ts} +78 -2
  3. package/dist/{chunk-OPCWH3A4.js → chunk-4YMVZ76F.js} +7 -6
  4. package/dist/chunk-4YMVZ76F.js.map +1 -0
  5. package/dist/{chunk-NN45OBIS.js → chunk-5G7JA3L5.js} +3 -5
  6. package/dist/{chunk-NN45OBIS.js.map → chunk-5G7JA3L5.js.map} +1 -1
  7. package/dist/{chunk-U6GPOF6J.js → chunk-5NV76BYF.js} +666 -110
  8. package/dist/chunk-5NV76BYF.js.map +1 -0
  9. package/dist/{chunk-D7ARGIA3.js → chunk-6RBH67W7.js} +23 -6
  10. package/dist/chunk-6RBH67W7.js.map +1 -0
  11. package/dist/{chunk-ZPG4XPV5.js → chunk-BHBMXMLT.js} +5 -7
  12. package/dist/chunk-BHBMXMLT.js.map +1 -0
  13. package/dist/{chunk-ZMS23NS5.js → chunk-FOT3WUV6.js} +3 -5
  14. package/dist/{chunk-ZMS23NS5.js.map → chunk-FOT3WUV6.js.map} +1 -1
  15. package/dist/{chunk-MOJXHWDE.js → chunk-GCUIIBLB.js} +382 -5
  16. package/dist/chunk-GCUIIBLB.js.map +1 -0
  17. package/dist/{chunk-PXWEDX7Y.js → chunk-KWQH4VO3.js} +3 -3
  18. package/dist/{chunk-ZPK5656W.js → chunk-O3NWNXDY.js} +4 -5
  19. package/dist/chunk-O3NWNXDY.js.map +1 -0
  20. package/dist/{chunk-KRCRNXPD.js → chunk-OTJUAYBG.js} +81 -18
  21. package/dist/chunk-OTJUAYBG.js.map +1 -0
  22. package/dist/chunk-SMJZMKYN.js +141 -0
  23. package/dist/chunk-SMJZMKYN.js.map +1 -0
  24. package/dist/{chunk-UYA6U6H7.js → chunk-V2TE7LOF.js} +4 -4
  25. package/dist/{chunk-L3RV2ALE.js → chunk-VKOCWWVY.js} +6 -1
  26. package/dist/{chunk-L3RV2ALE.js.map → chunk-VKOCWWVY.js.map} +1 -1
  27. package/dist/components.d.ts +4 -79
  28. package/dist/components.js +23 -581
  29. package/dist/components.js.map +1 -1
  30. package/dist/hooks.d.ts +1 -1
  31. package/dist/hooks.js +9 -6
  32. package/dist/hooks.js.map +1 -1
  33. package/dist/index.d.ts +4 -3
  34. package/dist/index.js +32 -19
  35. package/dist/index.js.map +1 -1
  36. package/dist/providers.js +6 -7
  37. package/dist/rbac/index.js +6 -6
  38. package/dist/styles/index.js +2 -2
  39. package/dist/theming/runtime.d.ts +4 -3
  40. package/dist/theming/runtime.js +3 -1
  41. package/dist/{usePublicRouteParams-CdoFxnJK.d.ts → usePublicRouteParams-Ua1Vz-HG.d.ts} +35 -1
  42. package/dist/utils.d.ts +4 -1
  43. package/dist/utils.js +3 -3
  44. package/docs/DOCUMENTATION_CHECKLIST.md +281 -0
  45. package/docs/README.md +22 -10
  46. package/docs/api/classes/ColumnFactory.md +1 -1
  47. package/docs/api/classes/ErrorBoundary.md +1 -1
  48. package/docs/api/classes/InvalidScopeError.md +1 -1
  49. package/docs/api/classes/MissingUserContextError.md +1 -1
  50. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  51. package/docs/api/classes/PermissionDeniedError.md +1 -1
  52. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  53. package/docs/api/classes/RBACAuditManager.md +1 -1
  54. package/docs/api/classes/RBACCache.md +1 -1
  55. package/docs/api/classes/RBACEngine.md +1 -1
  56. package/docs/api/classes/RBACError.md +1 -1
  57. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  58. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  59. package/docs/api/classes/StorageUtils.md +1 -1
  60. package/docs/api/enums/FileCategory.md +129 -0
  61. package/docs/api/interfaces/AggregateConfig.md +1 -1
  62. package/docs/api/interfaces/ButtonProps.md +1 -1
  63. package/docs/api/interfaces/CardProps.md +1 -1
  64. package/docs/api/interfaces/ColorPalette.md +1 -1
  65. package/docs/api/interfaces/ColorShade.md +1 -1
  66. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  67. package/docs/api/interfaces/DataTableAction.md +1 -1
  68. package/docs/api/interfaces/DataTableColumn.md +1 -1
  69. package/docs/api/interfaces/DataTableProps.md +1 -1
  70. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  71. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  72. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  73. package/docs/api/interfaces/EventContextType.md +7 -7
  74. package/docs/api/interfaces/EventLogoProps.md +1 -1
  75. package/docs/api/interfaces/EventProviderProps.md +2 -2
  76. package/docs/api/interfaces/FileDisplayProps.md +107 -0
  77. package/docs/api/interfaces/FileMetadata.md +129 -0
  78. package/docs/api/interfaces/FileReference.md +118 -0
  79. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  80. package/docs/api/interfaces/FileUploadOptions.md +85 -0
  81. package/docs/api/interfaces/FileUploadProps.md +1 -1
  82. package/docs/api/interfaces/FooterProps.md +1 -1
  83. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  84. package/docs/api/interfaces/InputProps.md +1 -1
  85. package/docs/api/interfaces/LabelProps.md +1 -1
  86. package/docs/api/interfaces/LoginFormProps.md +1 -1
  87. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  88. package/docs/api/interfaces/NavigationContextType.md +1 -1
  89. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  90. package/docs/api/interfaces/NavigationItem.md +1 -1
  91. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  92. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  93. package/docs/api/interfaces/Organisation.md +1 -1
  94. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  95. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  96. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  97. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  98. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  99. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  100. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  101. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  102. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  103. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  104. package/docs/api/interfaces/PaletteData.md +1 -1
  105. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  106. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  107. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  108. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  109. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  110. package/docs/api/interfaces/PublicPageHeaderProps.md +2 -2
  111. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  112. package/docs/api/interfaces/RBACConfig.md +1 -1
  113. package/docs/api/interfaces/RBACContextType.md +1 -1
  114. package/docs/api/interfaces/RBACLogger.md +1 -1
  115. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  116. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  117. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  118. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  119. package/docs/api/interfaces/RouteConfig.md +1 -1
  120. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  121. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  122. package/docs/api/interfaces/StorageConfig.md +1 -1
  123. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  124. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  125. package/docs/api/interfaces/StorageListOptions.md +1 -1
  126. package/docs/api/interfaces/StorageListResult.md +1 -1
  127. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  128. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  129. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  130. package/docs/api/interfaces/StyleImport.md +1 -1
  131. package/docs/api/interfaces/SwitchProps.md +1 -1
  132. package/docs/api/interfaces/ToastActionElement.md +1 -1
  133. package/docs/api/interfaces/ToastProps.md +1 -1
  134. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  135. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  136. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  137. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  138. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  139. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  140. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  141. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  142. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  143. package/docs/api/interfaces/UserEventAccess.md +1 -1
  144. package/docs/api/interfaces/UserMenuProps.md +1 -1
  145. package/docs/api/interfaces/UserProfile.md +1 -1
  146. package/docs/api/modules.md +228 -23
  147. package/docs/architecture/services.md +374 -0
  148. package/docs/best-practices/README.md +1 -1
  149. package/docs/best-practices/testing.md +1 -1
  150. package/docs/breaking-changes.md +182 -0
  151. package/docs/common-patterns.md +445 -0
  152. package/docs/core-concepts/authentication.md +26 -11
  153. package/docs/core-concepts/events.md +2 -0
  154. package/docs/core-concepts/organisations.md +2 -0
  155. package/docs/core-concepts/permissions.md +2 -0
  156. package/docs/{INDEX.md → documentation-index.md} +26 -38
  157. package/docs/faq.md +286 -0
  158. package/docs/{FILE_REFERENCE_SYSTEM.md → file-reference-system.md} +1 -1
  159. package/docs/getting-started/installation-guide.md +284 -0
  160. package/docs/getting-started/quick-start.md +8 -1
  161. package/docs/implementation-guides/app-layout.md +3 -1
  162. package/docs/implementation-guides/data-tables.md +2 -0
  163. package/docs/implementation-guides/dynamic-colors.md +47 -2
  164. package/docs/implementation-guides/event-theming-summary.md +220 -0
  165. package/docs/implementation-guides/forms.md +9 -7
  166. package/docs/implementation-guides/navigation.md +2 -0
  167. package/docs/migration/service-architecture.md +351 -0
  168. package/docs/rbac/README-rbac-rls-integration.md +2 -2
  169. package/docs/rbac/README.md +1 -1
  170. package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
  171. package/docs/rbac/quick-start.md +2 -0
  172. package/docs/rbac/rbac-rls-integration.md +2 -2
  173. package/docs/style-guide.md +136 -1
  174. package/docs/testing/README.md +1 -1
  175. package/docs/troubleshooting/authentication-issues.md +334 -0
  176. package/docs/troubleshooting/common-issues.md +2 -0
  177. package/docs/troubleshooting/styling-issues.md +199 -144
  178. package/docs/usage.md +23 -2
  179. package/package.json +3 -2
  180. package/src/__tests__/{TESTING_GUIDELINES.md → TEST_GUIDE_CURSOR.md} +20 -0
  181. package/src/__tests__/TEST_GUIDE_HUMAN.md +103 -0
  182. package/src/__tests__/fixtures/test-data.ts +90 -0
  183. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +260 -0
  184. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +224 -0
  185. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +273 -0
  186. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +98 -0
  187. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +436 -0
  188. package/src/__tests__/helpers/__tests__/timer-utils.test.ts +371 -0
  189. package/src/__tests__/helpers/component-test-utils.tsx +14 -4
  190. package/src/__tests__/helpers/optimized-test-setup.ts +68 -0
  191. package/src/__tests__/helpers/test-providers.tsx +329 -0
  192. package/src/__tests__/helpers/test-utils.tsx +91 -45
  193. package/src/__tests__/helpers/timer-utils.ts +71 -0
  194. package/src/__tests__/hooks/usePermissions.test.ts +1 -5
  195. package/src/__tests__/integration/UserProfile.test.tsx +1 -5
  196. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +42 -12
  197. package/src/__tests__/setup.ts +34 -28
  198. package/src/components/Alert/Alert.test.tsx +1 -5
  199. package/src/components/Avatar/Avatar.test.tsx +1 -5
  200. package/src/components/Button/Button.test.tsx +4 -20
  201. package/src/components/Card/Card.test.tsx +1 -5
  202. package/src/components/Checkbox/Checkbox.test.tsx +1 -5
  203. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -5
  204. package/src/components/DataTable/__tests__/DataTable.test.tsx +45 -49
  205. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +1 -5
  206. package/src/components/DataTable/__tests__/styles.test.ts +382 -0
  207. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +409 -0
  208. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +634 -0
  209. package/src/components/DataTable/core/__tests__/DataManager.test.ts +519 -0
  210. package/src/components/DataTable/core/__tests__/StateManager.test.ts +714 -0
  211. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +592 -0
  212. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +354 -0
  213. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +539 -0
  214. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +1 -5
  215. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +1 -8
  216. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +34 -38
  217. package/src/components/Footer/Footer.test.tsx +1 -5
  218. package/src/components/Form/Form.test.tsx +22 -35
  219. package/src/components/Header/Header.test.tsx +1 -9
  220. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +1 -5
  221. package/src/components/Input/Input.test.tsx +2 -10
  222. package/src/components/LoginForm/LoginForm.test.tsx +1 -5
  223. package/src/components/NavigationMenu/NavigationMenu.test.tsx +24 -24
  224. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +1 -6
  225. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -16
  226. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +1 -4
  227. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +1 -5
  228. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +1 -7
  229. package/src/components/PasswordReset/PasswordChangeForm.test.tsx +1 -9
  230. package/src/components/PasswordReset/PasswordResetForm.test.tsx +1 -9
  231. package/src/components/PublicLayout/PublicErrorBoundary.tsx +4 -5
  232. package/src/components/PublicLayout/PublicPageHeader.tsx +13 -9
  233. package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +666 -0
  234. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +457 -0
  235. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +393 -0
  236. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +351 -0
  237. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +374 -0
  238. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +388 -0
  239. package/src/components/Select/Select.bug-test.tsx +69 -0
  240. package/src/components/Select/Select.refactored.tsx +497 -0
  241. package/src/components/Select/Select.test.tsx +42 -49
  242. package/src/components/Select/Select.tsx +5 -2
  243. package/src/components/Select/hooks.ts +254 -0
  244. package/src/components/Switch/Switch.test.tsx +1 -5
  245. package/src/components/Table/__tests__/Table.test.tsx +775 -0
  246. package/src/components/Toast/Toast.test.tsx +15 -8
  247. package/src/components/Tooltip/Tooltip.test.tsx +1 -5
  248. package/src/components/UserMenu/UserMenu.test.tsx +3 -15
  249. package/src/components/__tests__/FileDisplay.test.tsx +575 -0
  250. package/src/components/__tests__/FileUpload.test.tsx +446 -0
  251. package/src/components/__tests__/SuperAdminGuard.test.tsx +422 -354
  252. package/src/hooks/__tests__/ServiceHooks.test.tsx +613 -0
  253. package/src/hooks/__tests__/hooks.integration.test.tsx +1 -10
  254. package/src/hooks/__tests__/useApiFetch.unit.test.ts +10 -14
  255. package/src/hooks/__tests__/useAppConfig.unit.test.ts +307 -0
  256. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +1 -6
  257. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +1 -5
  258. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +6 -9
  259. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +321 -0
  260. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +583 -0
  261. package/src/hooks/__tests__/usePublicEventLogo.unit.test.ts +640 -0
  262. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +435 -0
  263. package/src/hooks/__tests__/useRBAC.unit.test.ts +10 -10
  264. package/src/hooks/__tests__/useStorage.unit.test.ts +751 -0
  265. package/src/hooks/index.ts +3 -0
  266. package/src/hooks/public/usePublicEvent.ts +30 -9
  267. package/src/hooks/public/usePublicRouteParams.ts +13 -3
  268. package/src/hooks/services/useAuth.ts +50 -0
  269. package/src/hooks/services/useAuthService.ts +30 -0
  270. package/src/hooks/services/useCurrentEvent.ts +36 -0
  271. package/src/hooks/services/useCurrentOrganisation.ts +52 -0
  272. package/src/hooks/services/useEventService.ts +30 -0
  273. package/src/hooks/services/useInactivityService.ts +30 -0
  274. package/src/hooks/services/useOrganisationService.ts +30 -0
  275. package/src/hooks/services/usePermissions.ts +70 -0
  276. package/src/hooks/services/useRBACService.ts +30 -0
  277. package/src/hooks/useCounter.test.ts +1 -5
  278. package/src/hooks/useEventTheme.ts +86 -0
  279. package/src/hooks/useOrganisationPermissions.test.ts +2 -5
  280. package/src/hooks/useOrganisationSecurity.test.ts +1 -5
  281. package/src/hooks/usePermissionCache.test.ts +1 -5
  282. package/src/hooks/usePermissionCheck.ts +150 -0
  283. package/src/hooks/useSecureDataAccess.test.ts +1 -5
  284. package/src/index.ts +7 -0
  285. package/src/providers/EventProvider.tsx +58 -2
  286. package/src/providers/OrganisationProvider.test.tsx +1 -5
  287. package/src/providers/OrganisationProvider.tsx +56 -4
  288. package/src/providers/UnifiedAuthProvider.test.tsx +1 -5
  289. package/src/providers/__tests__/AuthProvider.test.tsx +105 -439
  290. package/src/providers/__tests__/AuthProvider.test.tsx.backup +771 -0
  291. package/src/providers/__tests__/EventProvider.test.tsx +211 -110
  292. package/src/providers/__tests__/EventProvider.test.tsx.backup +824 -0
  293. package/src/providers/__tests__/InactivityProvider.test.tsx +1 -5
  294. package/src/providers/__tests__/OrganisationProvider.test.tsx +97 -261
  295. package/src/providers/__tests__/OrganisationProvider.test.tsx.backup +820 -0
  296. package/src/providers/__tests__/ServiceProviders.test.tsx +477 -0
  297. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +72 -504
  298. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup +911 -0
  299. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup2 +166 -0
  300. package/src/providers/services/AuthServiceProvider.tsx +65 -0
  301. package/src/providers/services/EventServiceProvider.tsx +83 -0
  302. package/src/providers/services/InactivityServiceProvider.tsx +83 -0
  303. package/src/providers/services/OrganisationServiceProvider.tsx +77 -0
  304. package/src/providers/services/RBACServiceProvider.tsx +79 -0
  305. package/src/providers/services/UnifiedAuthProvider.tsx +368 -0
  306. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +210 -0
  307. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +269 -0
  308. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +892 -0
  309. package/src/rbac/__tests__/engine.comprehensive.test.ts +954 -0
  310. package/src/rbac/__tests__/integration.authflow.test.tsx +1 -5
  311. package/src/rbac/__tests__/integration.navigation.test.tsx +1 -4
  312. package/src/rbac/__tests__/rbac-core.test.tsx +2 -7
  313. package/src/rbac/__tests__/rbac-functions.test.ts +1 -9
  314. package/src/rbac/__tests__/rbac-integration.test.ts +1 -9
  315. package/src/rbac/api.test.ts +1 -9
  316. package/src/rbac/cache.test.ts +10 -8
  317. package/src/rbac/cli/__tests__/policy-manager.test.ts +339 -0
  318. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +1 -5
  319. package/src/rbac/components/NavigationProvider.test.tsx +1 -5
  320. package/src/rbac/components/PagePermissionProvider.test.tsx +1 -5
  321. package/src/rbac/components/SecureDataProvider.test.tsx +1 -5
  322. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +25 -29
  323. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +27 -30
  324. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +23 -27
  325. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +18 -22
  326. package/src/rbac/config.test.ts +1 -5
  327. package/src/rbac/hooks/useCan.test.ts +262 -9
  328. package/src/rbac/hooks/usePermissions.test.ts +246 -6
  329. package/src/rbac/hooks/useRBAC.simple.test.ts +1 -5
  330. package/src/rbac/hooks/useRBAC.test.ts +472 -198
  331. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +1 -9
  332. package/src/services/AuthService.ts +416 -0
  333. package/src/services/EventService.ts +366 -0
  334. package/src/services/InactivityService.ts +388 -0
  335. package/src/services/OrganisationService.ts +592 -0
  336. package/src/services/RBACService.ts +522 -0
  337. package/src/services/__tests__/AuthService.test.ts +356 -0
  338. package/src/services/__tests__/BaseService.test.ts +314 -0
  339. package/src/services/__tests__/EventService.test.ts +489 -0
  340. package/src/services/__tests__/InactivityService.test.ts +403 -0
  341. package/src/services/__tests__/OrganisationService.test.ts +660 -0
  342. package/src/services/__tests__/RBACService.test.ts +492 -0
  343. package/src/services/base/BaseService.ts +87 -0
  344. package/src/services/interfaces/IAuthService.ts +39 -0
  345. package/src/services/interfaces/IEventService.ts +30 -0
  346. package/src/services/interfaces/IInactivityService.ts +31 -0
  347. package/src/services/interfaces/IOrganisationService.ts +41 -0
  348. package/src/services/interfaces/IRBACService.ts +62 -0
  349. package/src/theming/__tests__/runtime.test.ts +560 -0
  350. package/src/theming/runtime.ts +71 -28
  351. package/src/types/__tests__/file-reference.test.ts +447 -0
  352. package/src/types/__tests__/organisation.test.ts +1133 -0
  353. package/src/types/__tests__/theme.test.ts +830 -0
  354. package/src/types/__tests__/type-validation.test.ts +527 -0
  355. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +1 -5
  356. package/src/utils/__tests__/debugLogger.test.ts +417 -0
  357. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -6
  358. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -5
  359. package/src/utils/__tests__/lazyLoad.unit.test.tsx +35 -35
  360. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -5
  361. package/src/utils/__tests__/performanceBudgets.unit.test.ts +5 -11
  362. package/src/utils/__tests__/secureErrors.unit.test.ts +1 -6
  363. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -5
  364. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -5
  365. package/src/utils/__tests__/sessionTracking.unit.test.ts +1 -5
  366. package/src/utils/appIdResolver.test.ts +6 -10
  367. package/src/utils/appNameResolver.simple.test.ts +142 -0
  368. package/src/utils/appNameResolver.test.ts +31 -458
  369. package/src/utils/appNameResolver.test.ts.backup +494 -0
  370. package/src/utils/debugLogger.ts +26 -5
  371. package/src/utils/formatDate.test.ts +1 -5
  372. package/src/utils/organisationContext.test.ts +1 -5
  373. package/src/utils/performanceBudgets.ts +3 -4
  374. package/src/utils/secureDataAccess.test.ts +1 -5
  375. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -5
  376. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +1 -5
  377. package/dist/chunk-D7ARGIA3.js.map +0 -1
  378. package/dist/chunk-IPCH4YPT.js +0 -315
  379. package/dist/chunk-IPCH4YPT.js.map +0 -1
  380. package/dist/chunk-KRCRNXPD.js.map +0 -1
  381. package/dist/chunk-MOJXHWDE.js.map +0 -1
  382. package/dist/chunk-N2EUGZRW.js +0 -98
  383. package/dist/chunk-N2EUGZRW.js.map +0 -1
  384. package/dist/chunk-OPCWH3A4.js.map +0 -1
  385. package/dist/chunk-U6GPOF6J.js.map +0 -1
  386. package/dist/chunk-ZPG4XPV5.js.map +0 -1
  387. package/dist/chunk-ZPK5656W.js.map +0 -1
  388. package/docs/getting-started/installation.md +0 -269
  389. package/src/__tests__/REBUILD_PLAN.md +0 -223
  390. package/src/styles/base.css +0 -208
  391. package/src/styles/semantic.css +0 -24
  392. /package/dist/{DataTable-4IUY7BXB.js.map → DataTable-OSELOGMA.js.map} +0 -0
  393. /package/dist/{chunk-PXWEDX7Y.js.map → chunk-KWQH4VO3.js.map} +0 -0
  394. /package/dist/{chunk-UYA6U6H7.js.map → chunk-V2TE7LOF.js.map} +0 -0
@@ -0,0 +1,1133 @@
1
+ /**
2
+ * @file Organisation Type Tests
3
+ * @package @jmruthers/pace-core
4
+ * @module Types/__tests__
5
+ * @since 1.0.0
6
+ */
7
+
8
+ import { describe, it, expect } from 'vitest';
9
+ import type {
10
+ Organisation,
11
+ OrganisationUser,
12
+ OrganisationRole,
13
+ OrganisationPermission,
14
+ OrganisationSettings,
15
+ OrganisationInvitation,
16
+ OrganisationMembership,
17
+ OrganisationContext,
18
+ OrganisationProviderProps,
19
+ OrganisationHookReturn,
20
+ OrganisationEvent,
21
+ OrganisationTheme,
22
+ OrganisationConfig,
23
+ OrganisationLimits,
24
+ OrganisationBilling,
25
+ OrganisationSubscription,
26
+ OrganisationFeature,
27
+ OrganisationIntegration,
28
+ OrganisationWebhook,
29
+ OrganisationAuditLog,
30
+ OrganisationAnalytics
31
+ } from '../organisation';
32
+
33
+ describe('[types] Organisation Types', () => {
34
+ describe('Organisation interface', () => {
35
+ it('validates Organisation type structure', () => {
36
+ const organisation: Organisation = {
37
+ id: 'org-123',
38
+ name: 'Test Organisation',
39
+ slug: 'test-org',
40
+ description: 'A test organisation',
41
+ logo_url: 'https://example.com/logo.png',
42
+ website: 'https://example.com',
43
+ email: 'contact@example.com',
44
+ phone: '+1234567890',
45
+ address: {
46
+ street: '123 Main St',
47
+ city: 'Test City',
48
+ state: 'TS',
49
+ postal_code: '12345',
50
+ country: 'US'
51
+ },
52
+ settings: {
53
+ timezone: 'UTC',
54
+ date_format: 'YYYY-MM-DD',
55
+ currency: 'USD',
56
+ language: 'en'
57
+ },
58
+ limits: {
59
+ max_users: 100,
60
+ max_events: 50,
61
+ max_storage_gb: 10
62
+ },
63
+ features: ['analytics', 'custom_branding', 'api_access'],
64
+ status: 'active',
65
+ created_at: '2024-01-01T00:00:00Z',
66
+ updated_at: '2024-01-01T00:00:00Z',
67
+ created_by: 'user-123'
68
+ };
69
+
70
+ expect(organisation).toHaveProperty('id');
71
+ expect(organisation).toHaveProperty('name');
72
+ expect(organisation).toHaveProperty('slug');
73
+ expect(organisation).toHaveProperty('description');
74
+ expect(organisation).toHaveProperty('logo_url');
75
+ expect(organisation).toHaveProperty('website');
76
+ expect(organisation).toHaveProperty('email');
77
+ expect(organisation).toHaveProperty('phone');
78
+ expect(organisation).toHaveProperty('address');
79
+ expect(organisation).toHaveProperty('settings');
80
+ expect(organisation).toHaveProperty('limits');
81
+ expect(organisation).toHaveProperty('features');
82
+ expect(organisation).toHaveProperty('status');
83
+ expect(organisation).toHaveProperty('created_at');
84
+ expect(organisation).toHaveProperty('updated_at');
85
+ expect(organisation).toHaveProperty('created_by');
86
+
87
+ expect(typeof organisation.id).toBe('string');
88
+ expect(typeof organisation.name).toBe('string');
89
+ expect(typeof organisation.slug).toBe('string');
90
+ expect(typeof organisation.description).toBe('string');
91
+ expect(typeof organisation.logo_url).toBe('string');
92
+ expect(typeof organisation.website).toBe('string');
93
+ expect(typeof organisation.email).toBe('string');
94
+ expect(typeof organisation.phone).toBe('string');
95
+ expect(typeof organisation.address).toBe('object');
96
+ expect(typeof organisation.settings).toBe('object');
97
+ expect(typeof organisation.limits).toBe('object');
98
+ expect(Array.isArray(organisation.features)).toBe(true);
99
+ expect(typeof organisation.status).toBe('string');
100
+ expect(typeof organisation.created_at).toBe('string');
101
+ expect(typeof organisation.updated_at).toBe('string');
102
+ expect(typeof organisation.created_by).toBe('string');
103
+ });
104
+
105
+ it('validates Organisation with minimal required fields', () => {
106
+ const organisation: Organisation = {
107
+ id: 'org-123',
108
+ name: 'Test Organisation',
109
+ slug: 'test-org',
110
+ status: 'active',
111
+ created_at: '2024-01-01T00:00:00Z',
112
+ updated_at: '2024-01-01T00:00:00Z',
113
+ created_by: 'user-123'
114
+ };
115
+
116
+ expect(organisation).toHaveProperty('id');
117
+ expect(organisation).toHaveProperty('name');
118
+ expect(organisation).toHaveProperty('slug');
119
+ expect(organisation).toHaveProperty('status');
120
+ expect(organisation).toHaveProperty('created_at');
121
+ expect(organisation).toHaveProperty('updated_at');
122
+ expect(organisation).toHaveProperty('created_by');
123
+ expect(organisation.description).toBeUndefined();
124
+ expect(organisation.logo_url).toBeUndefined();
125
+ expect(organisation.website).toBeUndefined();
126
+ expect(organisation.email).toBeUndefined();
127
+ expect(organisation.phone).toBeUndefined();
128
+ expect(organisation.address).toBeUndefined();
129
+ expect(organisation.settings).toBeUndefined();
130
+ expect(organisation.limits).toBeUndefined();
131
+ expect(organisation.features).toBeUndefined();
132
+ });
133
+ });
134
+
135
+ describe('OrganisationUser interface', () => {
136
+ it('validates OrganisationUser type structure', () => {
137
+ const orgUser: OrganisationUser = {
138
+ id: 'user-123',
139
+ organisation_id: 'org-123',
140
+ user_id: 'auth-user-123',
141
+ email: 'user@example.com',
142
+ first_name: 'John',
143
+ last_name: 'Doe',
144
+ avatar_url: 'https://example.com/avatar.jpg',
145
+ role: 'admin',
146
+ permissions: ['read:users', 'create:events', 'manage:all'],
147
+ status: 'active',
148
+ last_login: '2024-01-01T00:00:00Z',
149
+ created_at: '2024-01-01T00:00:00Z',
150
+ updated_at: '2024-01-01T00:00:00Z',
151
+ invited_by: 'admin-123',
152
+ invited_at: '2024-01-01T00:00:00Z'
153
+ };
154
+
155
+ expect(orgUser).toHaveProperty('id');
156
+ expect(orgUser).toHaveProperty('organisation_id');
157
+ expect(orgUser).toHaveProperty('user_id');
158
+ expect(orgUser).toHaveProperty('email');
159
+ expect(orgUser).toHaveProperty('first_name');
160
+ expect(orgUser).toHaveProperty('last_name');
161
+ expect(orgUser).toHaveProperty('avatar_url');
162
+ expect(orgUser).toHaveProperty('role');
163
+ expect(orgUser).toHaveProperty('permissions');
164
+ expect(orgUser).toHaveProperty('status');
165
+ expect(orgUser).toHaveProperty('last_login');
166
+ expect(orgUser).toHaveProperty('created_at');
167
+ expect(orgUser).toHaveProperty('updated_at');
168
+ expect(orgUser).toHaveProperty('invited_by');
169
+ expect(orgUser).toHaveProperty('invited_at');
170
+
171
+ expect(typeof orgUser.id).toBe('string');
172
+ expect(typeof orgUser.organisation_id).toBe('string');
173
+ expect(typeof orgUser.user_id).toBe('string');
174
+ expect(typeof orgUser.email).toBe('string');
175
+ expect(typeof orgUser.first_name).toBe('string');
176
+ expect(typeof orgUser.last_name).toBe('string');
177
+ expect(typeof orgUser.avatar_url).toBe('string');
178
+ expect(typeof orgUser.role).toBe('string');
179
+ expect(Array.isArray(orgUser.permissions)).toBe(true);
180
+ expect(typeof orgUser.status).toBe('string');
181
+ expect(typeof orgUser.last_login).toBe('string');
182
+ expect(typeof orgUser.created_at).toBe('string');
183
+ expect(typeof orgUser.updated_at).toBe('string');
184
+ expect(typeof orgUser.invited_by).toBe('string');
185
+ expect(typeof orgUser.invited_at).toBe('string');
186
+ });
187
+ });
188
+
189
+ describe('OrganisationRole interface', () => {
190
+ it('validates OrganisationRole type structure', () => {
191
+ const role: OrganisationRole = {
192
+ id: 'role-123',
193
+ organisation_id: 'org-123',
194
+ name: 'Event Manager',
195
+ description: 'Manages events and content',
196
+ permissions: ['read:events', 'create:events', 'update:events', 'delete:events'],
197
+ is_system_role: false,
198
+ is_default: false,
199
+ created_at: '2024-01-01T00:00:00Z',
200
+ updated_at: '2024-01-01T00:00:00Z',
201
+ created_by: 'admin-123'
202
+ };
203
+
204
+ expect(role).toHaveProperty('id');
205
+ expect(role).toHaveProperty('organisation_id');
206
+ expect(role).toHaveProperty('name');
207
+ expect(role).toHaveProperty('description');
208
+ expect(role).toHaveProperty('permissions');
209
+ expect(role).toHaveProperty('is_system_role');
210
+ expect(role).toHaveProperty('is_default');
211
+ expect(role).toHaveProperty('created_at');
212
+ expect(role).toHaveProperty('updated_at');
213
+ expect(role).toHaveProperty('created_by');
214
+
215
+ expect(typeof role.id).toBe('string');
216
+ expect(typeof role.organisation_id).toBe('string');
217
+ expect(typeof role.name).toBe('string');
218
+ expect(typeof role.description).toBe('string');
219
+ expect(Array.isArray(role.permissions)).toBe(true);
220
+ expect(typeof role.is_system_role).toBe('boolean');
221
+ expect(typeof role.is_default).toBe('boolean');
222
+ expect(typeof role.created_at).toBe('string');
223
+ expect(typeof role.updated_at).toBe('string');
224
+ expect(typeof role.created_by).toBe('string');
225
+ });
226
+ });
227
+
228
+ describe('OrganisationPermission interface', () => {
229
+ it('validates OrganisationPermission type structure', () => {
230
+ const permission: OrganisationPermission = {
231
+ id: 'perm-123',
232
+ organisation_id: 'org-123',
233
+ name: 'create:events',
234
+ description: 'Create new events',
235
+ resource: 'events',
236
+ action: 'create',
237
+ conditions: ['organisation_id = current_organisation_id()'],
238
+ created_at: '2024-01-01T00:00:00Z',
239
+ updated_at: '2024-01-01T00:00:00Z'
240
+ };
241
+
242
+ expect(permission).toHaveProperty('id');
243
+ expect(permission).toHaveProperty('organisation_id');
244
+ expect(permission).toHaveProperty('name');
245
+ expect(permission).toHaveProperty('description');
246
+ expect(permission).toHaveProperty('resource');
247
+ expect(permission).toHaveProperty('action');
248
+ expect(permission).toHaveProperty('conditions');
249
+ expect(permission).toHaveProperty('created_at');
250
+ expect(permission).toHaveProperty('updated_at');
251
+
252
+ expect(typeof permission.id).toBe('string');
253
+ expect(typeof permission.organisation_id).toBe('string');
254
+ expect(typeof permission.name).toBe('string');
255
+ expect(typeof permission.description).toBe('string');
256
+ expect(typeof permission.resource).toBe('string');
257
+ expect(typeof permission.action).toBe('string');
258
+ expect(Array.isArray(permission.conditions)).toBe(true);
259
+ expect(typeof permission.created_at).toBe('string');
260
+ expect(typeof permission.updated_at).toBe('string');
261
+ });
262
+ });
263
+
264
+ describe('OrganisationSettings interface', () => {
265
+ it('validates OrganisationSettings type structure', () => {
266
+ const settings: OrganisationSettings = {
267
+ timezone: 'UTC',
268
+ date_format: 'YYYY-MM-DD',
269
+ time_format: '24h',
270
+ currency: 'USD',
271
+ language: 'en',
272
+ theme: {
273
+ primary_color: '#0ea5e9',
274
+ secondary_color: '#64748b',
275
+ accent_color: '#ef4444'
276
+ },
277
+ notifications: {
278
+ email_enabled: true,
279
+ push_enabled: false,
280
+ sms_enabled: false
281
+ },
282
+ security: {
283
+ two_factor_required: false,
284
+ session_timeout: 3600,
285
+ password_policy: 'medium'
286
+ },
287
+ features: {
288
+ analytics_enabled: true,
289
+ custom_branding_enabled: false,
290
+ api_access_enabled: true
291
+ }
292
+ };
293
+
294
+ expect(settings).toHaveProperty('timezone');
295
+ expect(settings).toHaveProperty('date_format');
296
+ expect(settings).toHaveProperty('time_format');
297
+ expect(settings).toHaveProperty('currency');
298
+ expect(settings).toHaveProperty('language');
299
+ expect(settings).toHaveProperty('theme');
300
+ expect(settings).toHaveProperty('notifications');
301
+ expect(settings).toHaveProperty('security');
302
+ expect(settings).toHaveProperty('features');
303
+
304
+ expect(typeof settings.timezone).toBe('string');
305
+ expect(typeof settings.date_format).toBe('string');
306
+ expect(typeof settings.time_format).toBe('string');
307
+ expect(typeof settings.currency).toBe('string');
308
+ expect(typeof settings.language).toBe('string');
309
+ expect(typeof settings.theme).toBe('object');
310
+ expect(typeof settings.notifications).toBe('object');
311
+ expect(typeof settings.security).toBe('object');
312
+ expect(typeof settings.features).toBe('object');
313
+ });
314
+ });
315
+
316
+ describe('OrganisationInvitation interface', () => {
317
+ it('validates OrganisationInvitation type structure', () => {
318
+ const invitation: OrganisationInvitation = {
319
+ id: 'invite-123',
320
+ organisation_id: 'org-123',
321
+ email: 'newuser@example.com',
322
+ role: 'user',
323
+ permissions: ['read:events'],
324
+ status: 'pending',
325
+ token: 'invite-token-123',
326
+ expires_at: '2024-01-08T00:00:00Z',
327
+ invited_by: 'admin-123',
328
+ invited_at: '2024-01-01T00:00:00Z',
329
+ accepted_at: null,
330
+ created_at: '2024-01-01T00:00:00Z',
331
+ updated_at: '2024-01-01T00:00:00Z'
332
+ };
333
+
334
+ expect(invitation).toHaveProperty('id');
335
+ expect(invitation).toHaveProperty('organisation_id');
336
+ expect(invitation).toHaveProperty('email');
337
+ expect(invitation).toHaveProperty('role');
338
+ expect(invitation).toHaveProperty('permissions');
339
+ expect(invitation).toHaveProperty('status');
340
+ expect(invitation).toHaveProperty('token');
341
+ expect(invitation).toHaveProperty('expires_at');
342
+ expect(invitation).toHaveProperty('invited_by');
343
+ expect(invitation).toHaveProperty('invited_at');
344
+ expect(invitation).toHaveProperty('accepted_at');
345
+ expect(invitation).toHaveProperty('created_at');
346
+ expect(invitation).toHaveProperty('updated_at');
347
+
348
+ expect(typeof invitation.id).toBe('string');
349
+ expect(typeof invitation.organisation_id).toBe('string');
350
+ expect(typeof invitation.email).toBe('string');
351
+ expect(typeof invitation.role).toBe('string');
352
+ expect(Array.isArray(invitation.permissions)).toBe(true);
353
+ expect(typeof invitation.status).toBe('string');
354
+ expect(typeof invitation.token).toBe('string');
355
+ expect(typeof invitation.expires_at).toBe('string');
356
+ expect(typeof invitation.invited_by).toBe('string');
357
+ expect(typeof invitation.invited_at).toBe('string');
358
+ expect(invitation.accepted_at).toBeNull();
359
+ expect(typeof invitation.created_at).toBe('string');
360
+ expect(typeof invitation.updated_at).toBe('string');
361
+ });
362
+ });
363
+
364
+ describe('OrganisationMembership interface', () => {
365
+ it('validates OrganisationMembership type structure', () => {
366
+ const membership: OrganisationMembership = {
367
+ id: 'membership-123',
368
+ organisation_id: 'org-123',
369
+ user_id: 'user-123',
370
+ role: 'admin',
371
+ permissions: ['manage:all'],
372
+ status: 'active',
373
+ joined_at: '2024-01-01T00:00:00Z',
374
+ last_active: '2024-01-01T00:00:00Z',
375
+ created_at: '2024-01-01T00:00:00Z',
376
+ updated_at: '2024-01-01T00:00:00Z'
377
+ };
378
+
379
+ expect(membership).toHaveProperty('id');
380
+ expect(membership).toHaveProperty('organisation_id');
381
+ expect(membership).toHaveProperty('user_id');
382
+ expect(membership).toHaveProperty('role');
383
+ expect(membership).toHaveProperty('permissions');
384
+ expect(membership).toHaveProperty('status');
385
+ expect(membership).toHaveProperty('joined_at');
386
+ expect(membership).toHaveProperty('last_active');
387
+ expect(membership).toHaveProperty('created_at');
388
+ expect(membership).toHaveProperty('updated_at');
389
+
390
+ expect(typeof membership.id).toBe('string');
391
+ expect(typeof membership.organisation_id).toBe('string');
392
+ expect(typeof membership.user_id).toBe('string');
393
+ expect(typeof membership.role).toBe('string');
394
+ expect(Array.isArray(membership.permissions)).toBe(true);
395
+ expect(typeof membership.status).toBe('string');
396
+ expect(typeof membership.joined_at).toBe('string');
397
+ expect(typeof membership.last_active).toBe('string');
398
+ expect(typeof membership.created_at).toBe('string');
399
+ expect(typeof membership.updated_at).toBe('string');
400
+ });
401
+ });
402
+ });
403
+
404
+ describe('[types] Organisation Context Types', () => {
405
+ describe('OrganisationContext interface', () => {
406
+ it('validates OrganisationContext type structure', () => {
407
+ const context: OrganisationContext = {
408
+ organisation: {
409
+ id: 'org-123',
410
+ name: 'Test Organisation',
411
+ slug: 'test-org',
412
+ status: 'active',
413
+ created_at: '2024-01-01T00:00:00Z',
414
+ updated_at: '2024-01-01T00:00:00Z',
415
+ created_by: 'user-123'
416
+ },
417
+ user: {
418
+ id: 'user-123',
419
+ organisation_id: 'org-123',
420
+ user_id: 'auth-user-123',
421
+ email: 'user@example.com',
422
+ role: 'admin',
423
+ permissions: ['manage:all'],
424
+ status: 'active',
425
+ created_at: '2024-01-01T00:00:00Z',
426
+ updated_at: '2024-01-01T00:00:00Z'
427
+ },
428
+ permissions: ['manage:all'],
429
+ roles: ['admin'],
430
+ loading: false,
431
+ error: null,
432
+ switchOrganisation: () => {},
433
+ refreshOrganisation: () => {},
434
+ updateOrganisation: () => {},
435
+ inviteUser: () => {},
436
+ removeUser: () => {},
437
+ updateUserRole: () => {},
438
+ updateUserPermissions: () => {}
439
+ };
440
+
441
+ expect(context).toHaveProperty('organisation');
442
+ expect(context).toHaveProperty('user');
443
+ expect(context).toHaveProperty('permissions');
444
+ expect(context).toHaveProperty('roles');
445
+ expect(context).toHaveProperty('loading');
446
+ expect(context).toHaveProperty('error');
447
+ expect(context).toHaveProperty('switchOrganisation');
448
+ expect(context).toHaveProperty('refreshOrganisation');
449
+ expect(context).toHaveProperty('updateOrganisation');
450
+ expect(context).toHaveProperty('inviteUser');
451
+ expect(context).toHaveProperty('removeUser');
452
+ expect(context).toHaveProperty('updateUserRole');
453
+ expect(context).toHaveProperty('updateUserPermissions');
454
+
455
+ expect(typeof context.organisation).toBe('object');
456
+ expect(typeof context.user).toBe('object');
457
+ expect(Array.isArray(context.permissions)).toBe(true);
458
+ expect(Array.isArray(context.roles)).toBe(true);
459
+ expect(typeof context.loading).toBe('boolean');
460
+ expect(context.error).toBeNull();
461
+ expect(typeof context.switchOrganisation).toBe('function');
462
+ expect(typeof context.refreshOrganisation).toBe('function');
463
+ expect(typeof context.updateOrganisation).toBe('function');
464
+ expect(typeof context.inviteUser).toBe('function');
465
+ expect(typeof context.removeUser).toBe('function');
466
+ expect(typeof context.updateUserRole).toBe('function');
467
+ expect(typeof context.updateUserPermissions).toBe('function');
468
+ });
469
+ });
470
+
471
+ describe('OrganisationProviderProps interface', () => {
472
+ it('validates OrganisationProviderProps type structure', () => {
473
+ const props: OrganisationProviderProps = {
474
+ children: 'Test children',
475
+ organisationId: 'org-123',
476
+ userId: 'user-123',
477
+ autoRefresh: true,
478
+ refreshInterval: 30000,
479
+ onOrganisationChange: () => {},
480
+ onError: () => {}
481
+ };
482
+
483
+ expect(props).toHaveProperty('children');
484
+ expect(props).toHaveProperty('organisationId');
485
+ expect(props).toHaveProperty('userId');
486
+ expect(props).toHaveProperty('autoRefresh');
487
+ expect(props).toHaveProperty('refreshInterval');
488
+ expect(props).toHaveProperty('onOrganisationChange');
489
+ expect(props).toHaveProperty('onError');
490
+
491
+ expect(typeof props.children).toBe('string');
492
+ expect(typeof props.organisationId).toBe('string');
493
+ expect(typeof props.userId).toBe('string');
494
+ expect(typeof props.autoRefresh).toBe('boolean');
495
+ expect(typeof props.refreshInterval).toBe('number');
496
+ expect(typeof props.onOrganisationChange).toBe('function');
497
+ expect(typeof props.onError).toBe('function');
498
+ });
499
+ });
500
+
501
+ describe('OrganisationHookReturn interface', () => {
502
+ it('validates OrganisationHookReturn type structure', () => {
503
+ const hookReturn: OrganisationHookReturn = {
504
+ organisation: {
505
+ id: 'org-123',
506
+ name: 'Test Organisation',
507
+ slug: 'test-org',
508
+ status: 'active',
509
+ created_at: '2024-01-01T00:00:00Z',
510
+ updated_at: '2024-01-01T00:00:00Z',
511
+ created_by: 'user-123'
512
+ },
513
+ user: {
514
+ id: 'user-123',
515
+ organisation_id: 'org-123',
516
+ user_id: 'auth-user-123',
517
+ email: 'user@example.com',
518
+ role: 'admin',
519
+ permissions: ['manage:all'],
520
+ status: 'active',
521
+ created_at: '2024-01-01T00:00:00Z',
522
+ updated_at: '2024-01-01T00:00:00Z'
523
+ },
524
+ permissions: ['manage:all'],
525
+ roles: ['admin'],
526
+ loading: false,
527
+ error: null,
528
+ switchOrganisation: () => {},
529
+ refreshOrganisation: () => {},
530
+ updateOrganisation: () => {},
531
+ inviteUser: () => {},
532
+ removeUser: () => {},
533
+ updateUserRole: () => {},
534
+ updateUserPermissions: () => {},
535
+ hasPermission: () => true,
536
+ hasRole: () => true,
537
+ canAccess: () => true
538
+ };
539
+
540
+ expect(hookReturn).toHaveProperty('organisation');
541
+ expect(hookReturn).toHaveProperty('user');
542
+ expect(hookReturn).toHaveProperty('permissions');
543
+ expect(hookReturn).toHaveProperty('roles');
544
+ expect(hookReturn).toHaveProperty('loading');
545
+ expect(hookReturn).toHaveProperty('error');
546
+ expect(hookReturn).toHaveProperty('switchOrganisation');
547
+ expect(hookReturn).toHaveProperty('refreshOrganisation');
548
+ expect(hookReturn).toHaveProperty('updateOrganisation');
549
+ expect(hookReturn).toHaveProperty('inviteUser');
550
+ expect(hookReturn).toHaveProperty('removeUser');
551
+ expect(hookReturn).toHaveProperty('updateUserRole');
552
+ expect(hookReturn).toHaveProperty('updateUserPermissions');
553
+ expect(hookReturn).toHaveProperty('hasPermission');
554
+ expect(hookReturn).toHaveProperty('hasRole');
555
+ expect(hookReturn).toHaveProperty('canAccess');
556
+
557
+ expect(typeof hookReturn.organisation).toBe('object');
558
+ expect(typeof hookReturn.user).toBe('object');
559
+ expect(Array.isArray(hookReturn.permissions)).toBe(true);
560
+ expect(Array.isArray(hookReturn.roles)).toBe(true);
561
+ expect(typeof hookReturn.loading).toBe('boolean');
562
+ expect(hookReturn.error).toBeNull();
563
+ expect(typeof hookReturn.switchOrganisation).toBe('function');
564
+ expect(typeof hookReturn.refreshOrganisation).toBe('function');
565
+ expect(typeof hookReturn.updateOrganisation).toBe('function');
566
+ expect(typeof hookReturn.inviteUser).toBe('function');
567
+ expect(typeof hookReturn.removeUser).toBe('function');
568
+ expect(typeof hookReturn.updateUserRole).toBe('function');
569
+ expect(typeof hookReturn.updateUserPermissions).toBe('function');
570
+ expect(typeof hookReturn.hasPermission).toBe('function');
571
+ expect(typeof hookReturn.hasRole).toBe('function');
572
+ expect(typeof hookReturn.canAccess).toBe('function');
573
+ });
574
+ });
575
+ });
576
+
577
+ describe('[types] Organisation Extended Types', () => {
578
+ describe('OrganisationEvent interface', () => {
579
+ it('validates OrganisationEvent type structure', () => {
580
+ const orgEvent: OrganisationEvent = {
581
+ id: 'event-123',
582
+ organisation_id: 'org-123',
583
+ name: 'Test Event',
584
+ description: 'A test event',
585
+ start_date: '2024-01-01T00:00:00Z',
586
+ end_date: '2024-01-02T00:00:00Z',
587
+ status: 'active',
588
+ created_at: '2024-01-01T00:00:00Z',
589
+ updated_at: '2024-01-01T00:00:00Z'
590
+ };
591
+
592
+ expect(orgEvent).toHaveProperty('id');
593
+ expect(orgEvent).toHaveProperty('organisation_id');
594
+ expect(orgEvent).toHaveProperty('name');
595
+ expect(orgEvent).toHaveProperty('description');
596
+ expect(orgEvent).toHaveProperty('start_date');
597
+ expect(orgEvent).toHaveProperty('end_date');
598
+ expect(orgEvent).toHaveProperty('status');
599
+ expect(orgEvent).toHaveProperty('created_at');
600
+ expect(orgEvent).toHaveProperty('updated_at');
601
+
602
+ expect(typeof orgEvent.id).toBe('string');
603
+ expect(typeof orgEvent.organisation_id).toBe('string');
604
+ expect(typeof orgEvent.name).toBe('string');
605
+ expect(typeof orgEvent.description).toBe('string');
606
+ expect(typeof orgEvent.start_date).toBe('string');
607
+ expect(typeof orgEvent.end_date).toBe('string');
608
+ expect(typeof orgEvent.status).toBe('string');
609
+ expect(typeof orgEvent.created_at).toBe('string');
610
+ expect(typeof orgEvent.updated_at).toBe('string');
611
+ });
612
+ });
613
+
614
+ describe('OrganisationTheme interface', () => {
615
+ it('validates OrganisationTheme type structure', () => {
616
+ const theme: OrganisationTheme = {
617
+ id: 'theme-123',
618
+ organisation_id: 'org-123',
619
+ name: 'Custom Theme',
620
+ primary_color: '#0ea5e9',
621
+ secondary_color: '#64748b',
622
+ accent_color: '#ef4444',
623
+ background_color: '#ffffff',
624
+ text_color: '#000000',
625
+ is_default: false,
626
+ created_at: '2024-01-01T00:00:00Z',
627
+ updated_at: '2024-01-01T00:00:00Z'
628
+ };
629
+
630
+ expect(theme).toHaveProperty('id');
631
+ expect(theme).toHaveProperty('organisation_id');
632
+ expect(theme).toHaveProperty('name');
633
+ expect(theme).toHaveProperty('primary_color');
634
+ expect(theme).toHaveProperty('secondary_color');
635
+ expect(theme).toHaveProperty('accent_color');
636
+ expect(theme).toHaveProperty('background_color');
637
+ expect(theme).toHaveProperty('text_color');
638
+ expect(theme).toHaveProperty('is_default');
639
+ expect(theme).toHaveProperty('created_at');
640
+ expect(theme).toHaveProperty('updated_at');
641
+
642
+ expect(typeof theme.id).toBe('string');
643
+ expect(typeof theme.organisation_id).toBe('string');
644
+ expect(typeof theme.name).toBe('string');
645
+ expect(typeof theme.primary_color).toBe('string');
646
+ expect(typeof theme.secondary_color).toBe('string');
647
+ expect(typeof theme.accent_color).toBe('string');
648
+ expect(typeof theme.background_color).toBe('string');
649
+ expect(typeof theme.text_color).toBe('string');
650
+ expect(typeof theme.is_default).toBe('boolean');
651
+ expect(typeof theme.created_at).toBe('string');
652
+ expect(typeof theme.updated_at).toBe('string');
653
+ });
654
+ });
655
+
656
+ describe('OrganisationConfig interface', () => {
657
+ it('validates OrganisationConfig type structure', () => {
658
+ const config: OrganisationConfig = {
659
+ id: 'config-123',
660
+ organisation_id: 'org-123',
661
+ key: 'feature_flags',
662
+ value: {
663
+ analytics_enabled: true,
664
+ custom_branding_enabled: false,
665
+ api_access_enabled: true
666
+ },
667
+ created_at: '2024-01-01T00:00:00Z',
668
+ updated_at: '2024-01-01T00:00:00Z'
669
+ };
670
+
671
+ expect(config).toHaveProperty('id');
672
+ expect(config).toHaveProperty('organisation_id');
673
+ expect(config).toHaveProperty('key');
674
+ expect(config).toHaveProperty('value');
675
+ expect(config).toHaveProperty('created_at');
676
+ expect(config).toHaveProperty('updated_at');
677
+
678
+ expect(typeof config.id).toBe('string');
679
+ expect(typeof config.organisation_id).toBe('string');
680
+ expect(typeof config.key).toBe('string');
681
+ expect(typeof config.value).toBe('object');
682
+ expect(typeof config.created_at).toBe('string');
683
+ expect(typeof config.updated_at).toBe('string');
684
+ });
685
+ });
686
+
687
+ describe('OrganisationLimits interface', () => {
688
+ it('validates OrganisationLimits type structure', () => {
689
+ const limits: OrganisationLimits = {
690
+ max_users: 100,
691
+ max_events: 50,
692
+ max_storage_gb: 10,
693
+ max_api_calls_per_month: 10000,
694
+ max_webhooks: 5,
695
+ max_integrations: 3,
696
+ max_custom_fields: 20,
697
+ max_roles: 10,
698
+ max_permissions: 50
699
+ };
700
+
701
+ expect(limits).toHaveProperty('max_users');
702
+ expect(limits).toHaveProperty('max_events');
703
+ expect(limits).toHaveProperty('max_storage_gb');
704
+ expect(limits).toHaveProperty('max_api_calls_per_month');
705
+ expect(limits).toHaveProperty('max_webhooks');
706
+ expect(limits).toHaveProperty('max_integrations');
707
+ expect(limits).toHaveProperty('max_custom_fields');
708
+ expect(limits).toHaveProperty('max_roles');
709
+ expect(limits).toHaveProperty('max_permissions');
710
+
711
+ expect(typeof limits.max_users).toBe('number');
712
+ expect(typeof limits.max_events).toBe('number');
713
+ expect(typeof limits.max_storage_gb).toBe('number');
714
+ expect(typeof limits.max_api_calls_per_month).toBe('number');
715
+ expect(typeof limits.max_webhooks).toBe('number');
716
+ expect(typeof limits.max_integrations).toBe('number');
717
+ expect(typeof limits.max_custom_fields).toBe('number');
718
+ expect(typeof limits.max_roles).toBe('number');
719
+ expect(typeof limits.max_permissions).toBe('number');
720
+ });
721
+ });
722
+
723
+ describe('OrganisationBilling interface', () => {
724
+ it('validates OrganisationBilling type structure', () => {
725
+ const billing: OrganisationBilling = {
726
+ id: 'billing-123',
727
+ organisation_id: 'org-123',
728
+ plan: 'pro',
729
+ status: 'active',
730
+ current_period_start: '2024-01-01T00:00:00Z',
731
+ current_period_end: '2024-02-01T00:00:00Z',
732
+ cancel_at_period_end: false,
733
+ trial_end: null,
734
+ created_at: '2024-01-01T00:00:00Z',
735
+ updated_at: '2024-01-01T00:00:00Z'
736
+ };
737
+
738
+ expect(billing).toHaveProperty('id');
739
+ expect(billing).toHaveProperty('organisation_id');
740
+ expect(billing).toHaveProperty('plan');
741
+ expect(billing).toHaveProperty('status');
742
+ expect(billing).toHaveProperty('current_period_start');
743
+ expect(billing).toHaveProperty('current_period_end');
744
+ expect(billing).toHaveProperty('cancel_at_period_end');
745
+ expect(billing).toHaveProperty('trial_end');
746
+ expect(billing).toHaveProperty('created_at');
747
+ expect(billing).toHaveProperty('updated_at');
748
+
749
+ expect(typeof billing.id).toBe('string');
750
+ expect(typeof billing.organisation_id).toBe('string');
751
+ expect(typeof billing.plan).toBe('string');
752
+ expect(typeof billing.status).toBe('string');
753
+ expect(typeof billing.current_period_start).toBe('string');
754
+ expect(typeof billing.current_period_end).toBe('string');
755
+ expect(typeof billing.cancel_at_period_end).toBe('boolean');
756
+ expect(billing.trial_end).toBeNull();
757
+ expect(typeof billing.created_at).toBe('string');
758
+ expect(typeof billing.updated_at).toBe('string');
759
+ });
760
+ });
761
+
762
+ describe('OrganisationSubscription interface', () => {
763
+ it('validates OrganisationSubscription type structure', () => {
764
+ const subscription: OrganisationSubscription = {
765
+ id: 'sub-123',
766
+ organisation_id: 'org-123',
767
+ plan_id: 'plan-123',
768
+ status: 'active',
769
+ current_period_start: '2024-01-01T00:00:00Z',
770
+ current_period_end: '2024-02-01T00:00:00Z',
771
+ cancel_at_period_end: false,
772
+ trial_start: null,
773
+ trial_end: null,
774
+ created_at: '2024-01-01T00:00:00Z',
775
+ updated_at: '2024-01-01T00:00:00Z'
776
+ };
777
+
778
+ expect(subscription).toHaveProperty('id');
779
+ expect(subscription).toHaveProperty('organisation_id');
780
+ expect(subscription).toHaveProperty('plan_id');
781
+ expect(subscription).toHaveProperty('status');
782
+ expect(subscription).toHaveProperty('current_period_start');
783
+ expect(subscription).toHaveProperty('current_period_end');
784
+ expect(subscription).toHaveProperty('cancel_at_period_end');
785
+ expect(subscription).toHaveProperty('trial_start');
786
+ expect(subscription).toHaveProperty('trial_end');
787
+ expect(subscription).toHaveProperty('created_at');
788
+ expect(subscription).toHaveProperty('updated_at');
789
+
790
+ expect(typeof subscription.id).toBe('string');
791
+ expect(typeof subscription.organisation_id).toBe('string');
792
+ expect(typeof subscription.plan_id).toBe('string');
793
+ expect(typeof subscription.status).toBe('string');
794
+ expect(typeof subscription.current_period_start).toBe('string');
795
+ expect(typeof subscription.current_period_end).toBe('string');
796
+ expect(typeof subscription.cancel_at_period_end).toBe('boolean');
797
+ expect(subscription.trial_start).toBeNull();
798
+ expect(subscription.trial_end).toBeNull();
799
+ expect(typeof subscription.created_at).toBe('string');
800
+ expect(typeof subscription.updated_at).toBe('string');
801
+ });
802
+ });
803
+
804
+ describe('OrganisationFeature interface', () => {
805
+ it('validates OrganisationFeature type structure', () => {
806
+ const feature: OrganisationFeature = {
807
+ id: 'feature-123',
808
+ organisation_id: 'org-123',
809
+ name: 'analytics',
810
+ enabled: true,
811
+ config: {
812
+ retention_days: 90,
813
+ track_events: true,
814
+ track_users: true
815
+ },
816
+ created_at: '2024-01-01T00:00:00Z',
817
+ updated_at: '2024-01-01T00:00:00Z'
818
+ };
819
+
820
+ expect(feature).toHaveProperty('id');
821
+ expect(feature).toHaveProperty('organisation_id');
822
+ expect(feature).toHaveProperty('name');
823
+ expect(feature).toHaveProperty('enabled');
824
+ expect(feature).toHaveProperty('config');
825
+ expect(feature).toHaveProperty('created_at');
826
+ expect(feature).toHaveProperty('updated_at');
827
+
828
+ expect(typeof feature.id).toBe('string');
829
+ expect(typeof feature.organisation_id).toBe('string');
830
+ expect(typeof feature.name).toBe('string');
831
+ expect(typeof feature.enabled).toBe('boolean');
832
+ expect(typeof feature.config).toBe('object');
833
+ expect(typeof feature.created_at).toBe('string');
834
+ expect(typeof feature.updated_at).toBe('string');
835
+ });
836
+ });
837
+
838
+ describe('OrganisationIntegration interface', () => {
839
+ it('validates OrganisationIntegration type structure', () => {
840
+ const integration: OrganisationIntegration = {
841
+ id: 'integration-123',
842
+ organisation_id: 'org-123',
843
+ name: 'Slack',
844
+ type: 'webhook',
845
+ config: {
846
+ webhook_url: 'https://hooks.slack.com/services/...',
847
+ channel: '#notifications',
848
+ events: ['user.created', 'event.updated']
849
+ },
850
+ status: 'active',
851
+ last_sync: '2024-01-01T00:00:00Z',
852
+ created_at: '2024-01-01T00:00:00Z',
853
+ updated_at: '2024-01-01T00:00:00Z'
854
+ };
855
+
856
+ expect(integration).toHaveProperty('id');
857
+ expect(integration).toHaveProperty('organisation_id');
858
+ expect(integration).toHaveProperty('name');
859
+ expect(integration).toHaveProperty('type');
860
+ expect(integration).toHaveProperty('config');
861
+ expect(integration).toHaveProperty('status');
862
+ expect(integration).toHaveProperty('last_sync');
863
+ expect(integration).toHaveProperty('created_at');
864
+ expect(integration).toHaveProperty('updated_at');
865
+
866
+ expect(typeof integration.id).toBe('string');
867
+ expect(typeof integration.organisation_id).toBe('string');
868
+ expect(typeof integration.name).toBe('string');
869
+ expect(typeof integration.type).toBe('string');
870
+ expect(typeof integration.config).toBe('object');
871
+ expect(typeof integration.status).toBe('string');
872
+ expect(typeof integration.last_sync).toBe('string');
873
+ expect(typeof integration.created_at).toBe('string');
874
+ expect(typeof integration.updated_at).toBe('string');
875
+ });
876
+ });
877
+
878
+ describe('OrganisationWebhook interface', () => {
879
+ it('validates OrganisationWebhook type structure', () => {
880
+ const webhook: OrganisationWebhook = {
881
+ id: 'webhook-123',
882
+ organisation_id: 'org-123',
883
+ url: 'https://example.com/webhook',
884
+ events: ['user.created', 'event.updated', 'organisation.updated'],
885
+ secret: 'webhook-secret-123',
886
+ status: 'active',
887
+ last_triggered: '2024-01-01T00:00:00Z',
888
+ created_at: '2024-01-01T00:00:00Z',
889
+ updated_at: '2024-01-01T00:00:00Z'
890
+ };
891
+
892
+ expect(webhook).toHaveProperty('id');
893
+ expect(webhook).toHaveProperty('organisation_id');
894
+ expect(webhook).toHaveProperty('url');
895
+ expect(webhook).toHaveProperty('events');
896
+ expect(webhook).toHaveProperty('secret');
897
+ expect(webhook).toHaveProperty('status');
898
+ expect(webhook).toHaveProperty('last_triggered');
899
+ expect(webhook).toHaveProperty('created_at');
900
+ expect(webhook).toHaveProperty('updated_at');
901
+
902
+ expect(typeof webhook.id).toBe('string');
903
+ expect(typeof webhook.organisation_id).toBe('string');
904
+ expect(typeof webhook.url).toBe('string');
905
+ expect(Array.isArray(webhook.events)).toBe(true);
906
+ expect(typeof webhook.secret).toBe('string');
907
+ expect(typeof webhook.status).toBe('string');
908
+ expect(typeof webhook.last_triggered).toBe('string');
909
+ expect(typeof webhook.created_at).toBe('string');
910
+ expect(typeof webhook.updated_at).toBe('string');
911
+ });
912
+ });
913
+
914
+ describe('OrganisationAuditLog interface', () => {
915
+ it('validates OrganisationAuditLog type structure', () => {
916
+ const auditLog: OrganisationAuditLog = {
917
+ id: 'audit-123',
918
+ organisation_id: 'org-123',
919
+ user_id: 'user-123',
920
+ action: 'user.created',
921
+ resource: 'users',
922
+ resource_id: 'user-456',
923
+ details: {
924
+ email: 'newuser@example.com',
925
+ role: 'user',
926
+ permissions: ['read:events']
927
+ },
928
+ ip_address: '192.168.1.1',
929
+ user_agent: 'Mozilla/5.0...',
930
+ created_at: '2024-01-01T00:00:00Z'
931
+ };
932
+
933
+ expect(auditLog).toHaveProperty('id');
934
+ expect(auditLog).toHaveProperty('organisation_id');
935
+ expect(auditLog).toHaveProperty('user_id');
936
+ expect(auditLog).toHaveProperty('action');
937
+ expect(auditLog).toHaveProperty('resource');
938
+ expect(auditLog).toHaveProperty('resource_id');
939
+ expect(auditLog).toHaveProperty('details');
940
+ expect(auditLog).toHaveProperty('ip_address');
941
+ expect(auditLog).toHaveProperty('user_agent');
942
+ expect(auditLog).toHaveProperty('created_at');
943
+
944
+ expect(typeof auditLog.id).toBe('string');
945
+ expect(typeof auditLog.organisation_id).toBe('string');
946
+ expect(typeof auditLog.user_id).toBe('string');
947
+ expect(typeof auditLog.action).toBe('string');
948
+ expect(typeof auditLog.resource).toBe('string');
949
+ expect(typeof auditLog.resource_id).toBe('string');
950
+ expect(typeof auditLog.details).toBe('object');
951
+ expect(typeof auditLog.ip_address).toBe('string');
952
+ expect(typeof auditLog.user_agent).toBe('string');
953
+ expect(typeof auditLog.created_at).toBe('string');
954
+ });
955
+ });
956
+
957
+ describe('OrganisationAnalytics interface', () => {
958
+ it('validates OrganisationAnalytics type structure', () => {
959
+ const analytics: OrganisationAnalytics = {
960
+ id: 'analytics-123',
961
+ organisation_id: 'org-123',
962
+ metric: 'user_count',
963
+ value: 150,
964
+ date: '2024-01-01',
965
+ metadata: {
966
+ source: 'database',
967
+ calculation_method: 'count'
968
+ },
969
+ created_at: '2024-01-01T00:00:00Z'
970
+ };
971
+
972
+ expect(analytics).toHaveProperty('id');
973
+ expect(analytics).toHaveProperty('organisation_id');
974
+ expect(analytics).toHaveProperty('metric');
975
+ expect(analytics).toHaveProperty('value');
976
+ expect(analytics).toHaveProperty('date');
977
+ expect(analytics).toHaveProperty('metadata');
978
+ expect(analytics).toHaveProperty('created_at');
979
+
980
+ expect(typeof analytics.id).toBe('string');
981
+ expect(typeof analytics.organisation_id).toBe('string');
982
+ expect(typeof analytics.metric).toBe('string');
983
+ expect(typeof analytics.value).toBe('number');
984
+ expect(typeof analytics.date).toBe('string');
985
+ expect(typeof analytics.metadata).toBe('object');
986
+ expect(typeof analytics.created_at).toBe('string');
987
+ });
988
+ });
989
+ });
990
+
991
+ describe('[types] Organisation Usage Patterns', () => {
992
+ describe('Organisation Management Operations', () => {
993
+ it('validates organisation management operation types', () => {
994
+ interface OrganisationManagementOperation {
995
+ operation: 'create' | 'update' | 'delete' | 'invite' | 'remove' | 'switch';
996
+ organisationId: string;
997
+ data?: Partial<Organisation>;
998
+ userId?: string;
999
+ role?: string;
1000
+ permissions?: string[];
1001
+ }
1002
+
1003
+ const operations: OrganisationManagementOperation[] = [
1004
+ { operation: 'create', organisationId: 'org-123', data: { name: 'New Org' } },
1005
+ { operation: 'update', organisationId: 'org-123', data: { name: 'Updated Org' } },
1006
+ { operation: 'delete', organisationId: 'org-123' },
1007
+ { operation: 'invite', organisationId: 'org-123', userId: 'user-123', role: 'user' },
1008
+ { operation: 'remove', organisationId: 'org-123', userId: 'user-123' },
1009
+ { operation: 'switch', organisationId: 'org-456' }
1010
+ ];
1011
+
1012
+ operations.forEach(op => {
1013
+ expect(op).toHaveProperty('operation');
1014
+ expect(op).toHaveProperty('organisationId');
1015
+ expect(['create', 'update', 'delete', 'invite', 'remove', 'switch']).toContain(op.operation);
1016
+ expect(typeof op.organisationId).toBe('string');
1017
+ if (op.data) {
1018
+ expect(typeof op.data).toBe('object');
1019
+ }
1020
+ if (op.userId) {
1021
+ expect(typeof op.userId).toBe('string');
1022
+ }
1023
+ if (op.role) {
1024
+ expect(typeof op.role).toBe('string');
1025
+ }
1026
+ if (op.permissions) {
1027
+ expect(Array.isArray(op.permissions)).toBe(true);
1028
+ }
1029
+ });
1030
+ });
1031
+ });
1032
+
1033
+ describe('Organisation Permission Checks', () => {
1034
+ it('validates organisation permission check types', () => {
1035
+ interface OrganisationPermissionCheck {
1036
+ resource: string;
1037
+ action: string;
1038
+ organisationId: string;
1039
+ userId: string;
1040
+ context?: Record<string, any>;
1041
+ }
1042
+
1043
+ const permissionChecks: OrganisationPermissionCheck[] = [
1044
+ {
1045
+ resource: 'users',
1046
+ action: 'create',
1047
+ organisationId: 'org-123',
1048
+ userId: 'user-123'
1049
+ },
1050
+ {
1051
+ resource: 'events',
1052
+ action: 'update',
1053
+ organisationId: 'org-123',
1054
+ userId: 'user-123',
1055
+ context: { eventId: 'event-456' }
1056
+ }
1057
+ ];
1058
+
1059
+ permissionChecks.forEach(check => {
1060
+ expect(check).toHaveProperty('resource');
1061
+ expect(check).toHaveProperty('action');
1062
+ expect(check).toHaveProperty('organisationId');
1063
+ expect(check).toHaveProperty('userId');
1064
+ expect(typeof check.resource).toBe('string');
1065
+ expect(typeof check.action).toBe('string');
1066
+ expect(typeof check.organisationId).toBe('string');
1067
+ expect(typeof check.userId).toBe('string');
1068
+ if (check.context) {
1069
+ expect(typeof check.context).toBe('object');
1070
+ }
1071
+ });
1072
+ });
1073
+ });
1074
+
1075
+ describe('Organisation Data Validation', () => {
1076
+ it('validates organisation data validation types', () => {
1077
+ interface OrganisationDataValidation {
1078
+ field: keyof Organisation;
1079
+ value: any;
1080
+ rules: {
1081
+ required?: boolean;
1082
+ minLength?: number;
1083
+ maxLength?: number;
1084
+ pattern?: RegExp;
1085
+ custom?: (value: any) => boolean;
1086
+ };
1087
+ }
1088
+
1089
+ const validations: OrganisationDataValidation[] = [
1090
+ {
1091
+ field: 'name',
1092
+ value: 'Test Organisation',
1093
+ rules: {
1094
+ required: true,
1095
+ minLength: 2,
1096
+ maxLength: 100
1097
+ }
1098
+ },
1099
+ {
1100
+ field: 'email',
1101
+ value: 'contact@example.com',
1102
+ rules: {
1103
+ required: false,
1104
+ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
1105
+ }
1106
+ }
1107
+ ];
1108
+
1109
+ validations.forEach(validation => {
1110
+ expect(validation).toHaveProperty('field');
1111
+ expect(validation).toHaveProperty('value');
1112
+ expect(validation).toHaveProperty('rules');
1113
+ expect(typeof validation.field).toBe('string');
1114
+ expect(typeof validation.rules).toBe('object');
1115
+ if (validation.rules.required !== undefined) {
1116
+ expect(typeof validation.rules.required).toBe('boolean');
1117
+ }
1118
+ if (validation.rules.minLength !== undefined) {
1119
+ expect(typeof validation.rules.minLength).toBe('number');
1120
+ }
1121
+ if (validation.rules.maxLength !== undefined) {
1122
+ expect(typeof validation.rules.maxLength).toBe('number');
1123
+ }
1124
+ if (validation.rules.pattern !== undefined) {
1125
+ expect(validation.rules.pattern).toBeInstanceOf(RegExp);
1126
+ }
1127
+ if (validation.rules.custom !== undefined) {
1128
+ expect(typeof validation.rules.custom).toBe('function');
1129
+ }
1130
+ });
1131
+ });
1132
+ });
1133
+ });