@jmruthers/pace-core 0.5.4 → 0.5.5

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 (158) hide show
  1. package/dist/{DataTable-ZQDRE46Q.js → DataTable-3SSI644S.js} +2 -2
  2. package/dist/{chunk-M4RW7PIP.js → chunk-2BJFM2JC.js} +105 -81
  3. package/dist/chunk-2BJFM2JC.js.map +1 -0
  4. package/dist/{chunk-5H3C2SWM.js → chunk-RTCA5ZNK.js} +2 -2
  5. package/dist/components.js +2 -2
  6. package/dist/index.js +2 -2
  7. package/dist/utils.js +1 -1
  8. package/docs/api/classes/ErrorBoundary.md +1 -1
  9. package/docs/api/classes/InvalidScopeError.md +1 -1
  10. package/docs/api/classes/MissingUserContextError.md +1 -1
  11. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  12. package/docs/api/classes/PermissionDeniedError.md +1 -1
  13. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  14. package/docs/api/classes/RBACAuditManager.md +1 -1
  15. package/docs/api/classes/RBACCache.md +1 -1
  16. package/docs/api/classes/RBACEngine.md +1 -1
  17. package/docs/api/classes/RBACError.md +1 -1
  18. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  19. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  20. package/docs/api/interfaces/AggregateConfig.md +1 -1
  21. package/docs/api/interfaces/ButtonProps.md +1 -1
  22. package/docs/api/interfaces/CardProps.md +1 -1
  23. package/docs/api/interfaces/ColorPalette.md +1 -1
  24. package/docs/api/interfaces/ColorShade.md +1 -1
  25. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  26. package/docs/api/interfaces/DataTableAction.md +1 -1
  27. package/docs/api/interfaces/DataTableColumn.md +1 -1
  28. package/docs/api/interfaces/DataTableProps.md +34 -34
  29. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  30. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  31. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  32. package/docs/api/interfaces/EventContextType.md +1 -1
  33. package/docs/api/interfaces/EventLogoProps.md +1 -1
  34. package/docs/api/interfaces/EventProviderProps.md +1 -1
  35. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  36. package/docs/api/interfaces/FileUploadProps.md +1 -1
  37. package/docs/api/interfaces/FooterProps.md +1 -1
  38. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  39. package/docs/api/interfaces/InputProps.md +1 -1
  40. package/docs/api/interfaces/LabelProps.md +1 -1
  41. package/docs/api/interfaces/LoginFormProps.md +1 -1
  42. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  43. package/docs/api/interfaces/NavigationContextType.md +1 -1
  44. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  45. package/docs/api/interfaces/NavigationItem.md +1 -1
  46. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  47. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  48. package/docs/api/interfaces/Organisation.md +1 -1
  49. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  50. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  51. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  52. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  53. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  54. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  55. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  56. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  57. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  58. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  59. package/docs/api/interfaces/PaletteData.md +1 -1
  60. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  61. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  62. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  63. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  64. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  65. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  66. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  67. package/docs/api/interfaces/RBACConfig.md +1 -1
  68. package/docs/api/interfaces/RBACContextType.md +1 -1
  69. package/docs/api/interfaces/RBACLogger.md +1 -1
  70. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  71. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  72. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  73. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  74. package/docs/api/interfaces/RouteConfig.md +1 -1
  75. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  76. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  77. package/docs/api/interfaces/StorageConfig.md +1 -1
  78. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  79. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  80. package/docs/api/interfaces/StorageListOptions.md +1 -1
  81. package/docs/api/interfaces/StorageListResult.md +1 -1
  82. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  83. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  84. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  85. package/docs/api/interfaces/StyleImport.md +1 -1
  86. package/docs/api/interfaces/ToastActionElement.md +1 -1
  87. package/docs/api/interfaces/ToastProps.md +1 -1
  88. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  89. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  90. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  91. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  92. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  93. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  94. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  95. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  96. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  97. package/docs/api/interfaces/UserEventAccess.md +1 -1
  98. package/docs/api/interfaces/UserMenuProps.md +1 -1
  99. package/docs/api/interfaces/UserProfile.md +1 -1
  100. package/docs/api/modules.md +3 -3
  101. package/docs/implementation-guides/data-tables.md +20 -0
  102. package/docs/quick-reference.md +9 -0
  103. package/docs/rbac/examples.md +4 -0
  104. package/package.json +1 -1
  105. package/src/__tests__/helpers/test-utils.tsx +147 -1
  106. package/src/components/DataTable/DataTable.tsx +20 -0
  107. package/src/components/DataTable/__tests__/DataTable.hooks.test 2.tsx +191 -0
  108. package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +191 -0
  109. package/src/components/DataTable/components/DataTableCore.tsx +167 -138
  110. package/src/hooks/__tests__/hooks.integration.test.tsx +575 -0
  111. package/src/hooks/__tests__/useApiFetch.unit.test.ts +115 -0
  112. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +133 -0
  113. package/src/hooks/__tests__/useDebounce.unit.test.ts +82 -0
  114. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +293 -0
  115. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +385 -0
  116. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +286 -0
  117. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +838 -0
  118. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +104 -0
  119. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +633 -0
  120. package/src/hooks/__tests__/useRBAC.unit.test.ts +856 -0
  121. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +537 -0
  122. package/src/hooks/__tests__/useToast.unit.test.tsx +62 -0
  123. package/src/hooks/__tests__/useZodForm.unit.test.tsx +37 -0
  124. package/src/rbac/utils/__tests__/eventContext.test.ts +428 -0
  125. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +428 -0
  126. package/src/utils/__tests__/appConfig.unit.test.ts +55 -0
  127. package/src/utils/__tests__/audit.unit.test.ts +69 -0
  128. package/src/utils/__tests__/auth-utils.unit.test.ts +70 -0
  129. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +317 -0
  130. package/src/utils/__tests__/cn.unit.test.ts +34 -0
  131. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +503 -0
  132. package/src/utils/__tests__/dynamicUtils.unit.test.ts +322 -0
  133. package/src/utils/__tests__/formatDate.unit.test.ts +109 -0
  134. package/src/utils/__tests__/formatting.unit.test.ts +66 -0
  135. package/src/utils/__tests__/index.unit.test.ts +251 -0
  136. package/src/utils/__tests__/lazyLoad.unit.test.tsx +309 -0
  137. package/src/utils/__tests__/organisationContext.unit.test.ts +192 -0
  138. package/src/utils/__tests__/performanceBudgets.unit.test.ts +259 -0
  139. package/src/utils/__tests__/permissionTypes.unit.test.ts +250 -0
  140. package/src/utils/__tests__/permissionUtils.unit.test.ts +362 -0
  141. package/src/utils/__tests__/sanitization.unit.test.ts +346 -0
  142. package/src/utils/__tests__/schemaUtils.unit.test.ts +441 -0
  143. package/src/utils/__tests__/secureDataAccess.unit.test.ts +334 -0
  144. package/src/utils/__tests__/secureErrors.unit.test.ts +377 -0
  145. package/src/utils/__tests__/secureStorage.unit.test.ts +293 -0
  146. package/src/utils/__tests__/security.unit.test.ts +127 -0
  147. package/src/utils/__tests__/securityMonitor.unit.test.ts +280 -0
  148. package/src/utils/__tests__/sessionTracking.unit.test.ts +356 -0
  149. package/src/utils/__tests__/validation.unit.test.ts +84 -0
  150. package/src/utils/__tests__/validationUtils.unit.test.ts +571 -0
  151. package/src/validation/__tests__/common.unit.test.ts +101 -0
  152. package/src/validation/__tests__/csrf.unit.test.ts +302 -0
  153. package/src/validation/__tests__/passwordSchema.unit.test 2.ts +98 -0
  154. package/src/validation/__tests__/passwordSchema.unit.test.ts +98 -0
  155. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +466 -0
  156. package/dist/chunk-M4RW7PIP.js.map +0 -1
  157. /package/dist/{DataTable-ZQDRE46Q.js.map → DataTable-3SSI644S.js.map} +0 -0
  158. /package/dist/{chunk-5H3C2SWM.js.map → chunk-RTCA5ZNK.js.map} +0 -0
@@ -0,0 +1,362 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import {
3
+ transformPermissionMapToBoolean,
4
+ hasPermission,
5
+ hasAnyPermission,
6
+ hasAllPermissions
7
+ } from '../permissionUtils';
8
+
9
+ describe('permissionUtils', () => {
10
+ describe('transformPermissionMapToBoolean', () => {
11
+ it('should transform permission map to boolean values', () => {
12
+ const permissions = {
13
+ 'read:users': true,
14
+ 'write:users': false,
15
+ 'delete:users': 1,
16
+ 'admin:users': 0,
17
+ 'view:reports': 'true',
18
+ 'edit:reports': false
19
+ };
20
+
21
+ const result = transformPermissionMapToBoolean(permissions);
22
+
23
+ expect(result).toEqual({
24
+ 'read:users': true,
25
+ 'write:users': false,
26
+ 'delete:users': true,
27
+ 'admin:users': false,
28
+ 'view:reports': true,
29
+ 'edit:reports': false
30
+ });
31
+ });
32
+
33
+ it('should handle empty permission map', () => {
34
+ const permissions = {};
35
+
36
+ const result = transformPermissionMapToBoolean(permissions);
37
+
38
+ expect(result).toEqual({});
39
+ });
40
+
41
+ it('should handle various truthy and falsy values', () => {
42
+ const permissions = {
43
+ 'permission1': true,
44
+ 'permission2': false,
45
+ 'permission3': 1,
46
+ 'permission4': 0,
47
+ 'permission5': 'true',
48
+ 'permission6': 'false',
49
+ 'permission7': '',
50
+ 'permission8': null,
51
+ 'permission9': undefined
52
+ };
53
+
54
+ const result = transformPermissionMapToBoolean(permissions);
55
+
56
+ expect(result).toEqual({
57
+ 'permission1': true,
58
+ 'permission2': false,
59
+ 'permission3': true,
60
+ 'permission4': false,
61
+ 'permission5': true,
62
+ 'permission6': false,
63
+ 'permission7': false,
64
+ 'permission8': false,
65
+ 'permission9': false
66
+ });
67
+ });
68
+
69
+ it('should handle mixed data types', () => {
70
+ const permissions = {
71
+ 'read': true,
72
+ 'write': 'yes',
73
+ 'delete': 1,
74
+ 'admin': 'no',
75
+ 'view': 0,
76
+ 'edit': false
77
+ };
78
+
79
+ const result = transformPermissionMapToBoolean(permissions);
80
+
81
+ expect(result).toEqual({
82
+ 'read': true,
83
+ 'write': true,
84
+ 'delete': true,
85
+ 'admin': true,
86
+ 'view': false,
87
+ 'edit': false
88
+ });
89
+ });
90
+ });
91
+
92
+ describe('hasPermission', () => {
93
+ it('should return true when permission exists and is true', () => {
94
+ const permissions = {
95
+ 'read:users': true,
96
+ 'write:users': false,
97
+ 'delete:users': true
98
+ };
99
+
100
+ expect(hasPermission(permissions, 'read:users')).toBe(true);
101
+ expect(hasPermission(permissions, 'delete:users')).toBe(true);
102
+ });
103
+
104
+ it('should return false when permission exists but is false', () => {
105
+ const permissions = {
106
+ 'read:users': true,
107
+ 'write:users': false,
108
+ 'delete:users': true
109
+ };
110
+
111
+ expect(hasPermission(permissions, 'write:users')).toBe(false);
112
+ });
113
+
114
+ it('should return false when permission does not exist', () => {
115
+ const permissions = {
116
+ 'read:users': true,
117
+ 'write:users': false
118
+ };
119
+
120
+ expect(hasPermission(permissions, 'admin:users')).toBe(false);
121
+ });
122
+
123
+ it('should handle empty permissions object', () => {
124
+ const permissions = {};
125
+
126
+ expect(hasPermission(permissions, 'any:permission')).toBe(false);
127
+ });
128
+
129
+ it('should handle various truthy and falsy values', () => {
130
+ const permissions = {
131
+ 'truthy1': true,
132
+ 'truthy2': 1,
133
+ 'truthy3': 'true',
134
+ 'falsy1': false,
135
+ 'falsy2': 0,
136
+ 'falsy3': 'false',
137
+ 'falsy4': '',
138
+ 'falsy5': null,
139
+ 'falsy6': undefined
140
+ };
141
+
142
+ expect(hasPermission(permissions, 'truthy1')).toBe(true);
143
+ expect(hasPermission(permissions, 'truthy2')).toBe(true);
144
+ expect(hasPermission(permissions, 'truthy3')).toBe(true);
145
+ expect(hasPermission(permissions, 'falsy1')).toBe(false);
146
+ expect(hasPermission(permissions, 'falsy2')).toBe(false);
147
+ expect(hasPermission(permissions, 'falsy3')).toBe(true);
148
+ expect(hasPermission(permissions, 'falsy4')).toBe(false);
149
+ expect(hasPermission(permissions, 'falsy5')).toBe(false);
150
+ expect(hasPermission(permissions, 'falsy6')).toBe(false);
151
+ });
152
+ });
153
+
154
+ describe('hasAnyPermission', () => {
155
+ it('should return true when any permission in list is granted', () => {
156
+ const permissions = {
157
+ 'read:users': true,
158
+ 'write:users': false,
159
+ 'delete:users': false,
160
+ 'admin:users': true
161
+ };
162
+
163
+ expect(hasAnyPermission(permissions, ['read:users', 'write:users'])).toBe(true);
164
+ expect(hasAnyPermission(permissions, ['write:users', 'delete:users', 'admin:users'])).toBe(true);
165
+ });
166
+
167
+ it('should return false when no permissions in list are granted', () => {
168
+ const permissions = {
169
+ 'read:users': false,
170
+ 'write:users': false,
171
+ 'delete:users': false
172
+ };
173
+
174
+ expect(hasAnyPermission(permissions, ['read:users', 'write:users', 'delete:users'])).toBe(false);
175
+ });
176
+
177
+ it('should return false when permission list is empty', () => {
178
+ const permissions = {
179
+ 'read:users': true,
180
+ 'write:users': true
181
+ };
182
+
183
+ expect(hasAnyPermission(permissions, [])).toBe(false);
184
+ });
185
+
186
+ it('should return false when permissions object is empty', () => {
187
+ const permissions = {};
188
+
189
+ expect(hasAnyPermission(permissions, ['read:users', 'write:users'])).toBe(false);
190
+ });
191
+
192
+ it('should handle permissions that do not exist', () => {
193
+ const permissions = {
194
+ 'read:users': true,
195
+ 'write:users': false
196
+ };
197
+
198
+ expect(hasAnyPermission(permissions, ['read:users', 'nonexistent:permission'])).toBe(true);
199
+ expect(hasAnyPermission(permissions, ['nonexistent1:permission', 'nonexistent2:permission'])).toBe(false);
200
+ });
201
+
202
+ it('should handle single permission in list', () => {
203
+ const permissions = {
204
+ 'read:users': true,
205
+ 'write:users': false
206
+ };
207
+
208
+ expect(hasAnyPermission(permissions, ['read:users'])).toBe(true);
209
+ expect(hasAnyPermission(permissions, ['write:users'])).toBe(false);
210
+ });
211
+ });
212
+
213
+ describe('hasAllPermissions', () => {
214
+ it('should return true when all permissions in list are granted', () => {
215
+ const permissions = {
216
+ 'read:users': true,
217
+ 'write:users': true,
218
+ 'delete:users': true
219
+ };
220
+
221
+ expect(hasAllPermissions(permissions, ['read:users', 'write:users', 'delete:users'])).toBe(true);
222
+ });
223
+
224
+ it('should return false when any permission in list is not granted', () => {
225
+ const permissions = {
226
+ 'read:users': true,
227
+ 'write:users': false,
228
+ 'delete:users': true
229
+ };
230
+
231
+ expect(hasAllPermissions(permissions, ['read:users', 'write:users', 'delete:users'])).toBe(false);
232
+ });
233
+
234
+ it('should return true when permission list is empty', () => {
235
+ const permissions = {
236
+ 'read:users': true,
237
+ 'write:users': true
238
+ };
239
+
240
+ expect(hasAllPermissions(permissions, [])).toBe(true);
241
+ });
242
+
243
+ it('should return false when permissions object is empty but list is not', () => {
244
+ const permissions = {};
245
+
246
+ expect(hasAllPermissions(permissions, ['read:users', 'write:users'])).toBe(false);
247
+ });
248
+
249
+ it('should handle permissions that do not exist', () => {
250
+ const permissions = {
251
+ 'read:users': true,
252
+ 'write:users': true
253
+ };
254
+
255
+ expect(hasAllPermissions(permissions, ['read:users', 'nonexistent:permission'])).toBe(false);
256
+ expect(hasAllPermissions(permissions, ['nonexistent1:permission', 'nonexistent2:permission'])).toBe(false);
257
+ });
258
+
259
+ it('should handle single permission in list', () => {
260
+ const permissions = {
261
+ 'read:users': true,
262
+ 'write:users': false
263
+ };
264
+
265
+ expect(hasAllPermissions(permissions, ['read:users'])).toBe(true);
266
+ expect(hasAllPermissions(permissions, ['write:users'])).toBe(false);
267
+ });
268
+
269
+ it('should handle mixed existing and non-existing permissions', () => {
270
+ const permissions = {
271
+ 'read:users': true,
272
+ 'write:users': true
273
+ };
274
+
275
+ expect(hasAllPermissions(permissions, ['read:users', 'write:users', 'nonexistent:permission'])).toBe(false);
276
+ });
277
+ });
278
+
279
+ describe('Integration tests', () => {
280
+ it('should work together in a realistic permission scenario', () => {
281
+ const userPermissions = {
282
+ 'read:users': true,
283
+ 'write:users': false,
284
+ 'delete:users': false,
285
+ 'read:reports': true,
286
+ 'write:reports': true,
287
+ 'admin:system': false
288
+ };
289
+
290
+ // Transform permissions to ensure boolean values
291
+ const booleanPermissions = transformPermissionMapToBoolean(userPermissions);
292
+
293
+ // Check individual permissions
294
+ expect(hasPermission(booleanPermissions, 'read:users')).toBe(true);
295
+ expect(hasPermission(booleanPermissions, 'write:users')).toBe(false);
296
+ expect(hasPermission(booleanPermissions, 'admin:system')).toBe(false);
297
+
298
+ // Check if user has any user management permissions
299
+ expect(hasAnyPermission(booleanPermissions, ['read:users', 'write:users', 'delete:users'])).toBe(true);
300
+
301
+ // Check if user has all user management permissions
302
+ expect(hasAllPermissions(booleanPermissions, ['read:users', 'write:users', 'delete:users'])).toBe(false);
303
+
304
+ // Check if user has all report permissions
305
+ expect(hasAllPermissions(booleanPermissions, ['read:reports', 'write:reports'])).toBe(true);
306
+
307
+ // Check if user has any admin permissions
308
+ expect(hasAnyPermission(booleanPermissions, ['admin:system', 'admin:users'])).toBe(false);
309
+ });
310
+
311
+ it('should handle complex permission hierarchies', () => {
312
+ const adminPermissions = {
313
+ 'read:users': true,
314
+ 'write:users': true,
315
+ 'delete:users': true,
316
+ 'read:reports': true,
317
+ 'write:reports': true,
318
+ 'delete:reports': true,
319
+ 'admin:system': true
320
+ };
321
+
322
+ const managerPermissions = {
323
+ 'read:users': true,
324
+ 'write:users': true,
325
+ 'delete:users': false,
326
+ 'read:reports': true,
327
+ 'write:reports': true,
328
+ 'delete:reports': false,
329
+ 'admin:system': false
330
+ };
331
+
332
+ const userPermissions = {
333
+ 'read:users': true,
334
+ 'write:users': false,
335
+ 'delete:users': false,
336
+ 'read:reports': true,
337
+ 'write:reports': false,
338
+ 'delete:reports': false,
339
+ 'admin:system': false
340
+ };
341
+
342
+ const booleanAdminPermissions = transformPermissionMapToBoolean(adminPermissions);
343
+ const booleanManagerPermissions = transformPermissionMapToBoolean(managerPermissions);
344
+ const booleanUserPermissions = transformPermissionMapToBoolean(userPermissions);
345
+
346
+ // Admin should have all permissions
347
+ expect(hasAllPermissions(booleanAdminPermissions, ['read:users', 'write:users', 'delete:users'])).toBe(true);
348
+ expect(hasAllPermissions(booleanAdminPermissions, ['read:reports', 'write:reports', 'delete:reports'])).toBe(true);
349
+ expect(hasPermission(booleanAdminPermissions, 'admin:system')).toBe(true);
350
+
351
+ // Manager should have some but not all permissions
352
+ expect(hasAllPermissions(booleanManagerPermissions, ['read:users', 'write:users'])).toBe(true);
353
+ expect(hasAllPermissions(booleanManagerPermissions, ['read:users', 'write:users', 'delete:users'])).toBe(false);
354
+ expect(hasAnyPermission(booleanManagerPermissions, ['delete:users', 'delete:reports'])).toBe(false);
355
+
356
+ // User should have limited permissions
357
+ expect(hasAllPermissions(booleanUserPermissions, ['read:users', 'read:reports'])).toBe(true);
358
+ expect(hasAnyPermission(booleanUserPermissions, ['write:users', 'write:reports'])).toBe(false);
359
+ expect(hasPermission(booleanUserPermissions, 'admin:system')).toBe(false);
360
+ });
361
+ });
362
+ });