@jmruthers/pace-core 0.5.118 → 0.5.120

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 (181) hide show
  1. package/dist/{DataTable-ZOAKQ3SU.js → DataTable-DGZDJUYM.js} +7 -7
  2. package/dist/{UnifiedAuthProvider-YFN7YGVN.js → UnifiedAuthProvider-UACKFATV.js} +3 -3
  3. package/dist/{chunk-7OTQLFVI.js → chunk-B4GZ2BXO.js} +3 -3
  4. package/dist/{chunk-KA3PSVNV.js → chunk-BHWIUEYH.js} +2 -1
  5. package/dist/chunk-BHWIUEYH.js.map +1 -0
  6. package/dist/{chunk-LFS45U62.js → chunk-CGURJ27Z.js} +2 -2
  7. package/dist/{chunk-PHDAXDHB.js → chunk-D6BOFXYR.js} +3 -3
  8. package/dist/{chunk-P3PUOL6B.js → chunk-FKFHZUGF.js} +4 -4
  9. package/dist/{chunk-2GJ5GL77.js → chunk-GKHF54DI.js} +2 -2
  10. package/dist/chunk-GKHF54DI.js.map +1 -0
  11. package/dist/{chunk-UKZWNQMB.js → chunk-HFBOFZ3Z.js} +5 -18
  12. package/dist/chunk-HFBOFZ3Z.js.map +1 -0
  13. package/dist/{chunk-O3FTRYEU.js → chunk-NZ32EONV.js} +2 -2
  14. package/dist/{chunk-2LM4QQGH.js → chunk-QPI2CCBA.js} +9 -9
  15. package/dist/chunk-QPI2CCBA.js.map +1 -0
  16. package/dist/{chunk-ECOVPXYS.js → chunk-RIEJGKD3.js} +4 -4
  17. package/dist/{chunk-HIWXXDXO.js → chunk-TDNI6ZWL.js} +5 -5
  18. package/dist/{chunk-VN3OOE35.js → chunk-ZYJ6O5CA.js} +2 -2
  19. package/dist/components.d.ts +1 -1
  20. package/dist/components.js +9 -9
  21. package/dist/hooks.d.ts +1 -1
  22. package/dist/hooks.js +8 -8
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +12 -12
  25. package/dist/providers.js +2 -2
  26. package/dist/rbac/index.js +7 -7
  27. package/dist/{useToast-Cs_g32bg.d.ts → useToast-C8gR5ir4.d.ts} +2 -2
  28. package/dist/utils.js +1 -1
  29. package/docs/api/classes/ColumnFactory.md +1 -1
  30. package/docs/api/classes/ErrorBoundary.md +1 -1
  31. package/docs/api/classes/InvalidScopeError.md +1 -1
  32. package/docs/api/classes/MissingUserContextError.md +1 -1
  33. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  34. package/docs/api/classes/PermissionDeniedError.md +1 -1
  35. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  36. package/docs/api/classes/RBACAuditManager.md +1 -1
  37. package/docs/api/classes/RBACCache.md +1 -1
  38. package/docs/api/classes/RBACEngine.md +1 -1
  39. package/docs/api/classes/RBACError.md +1 -1
  40. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  41. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  42. package/docs/api/classes/StorageUtils.md +1 -1
  43. package/docs/api/enums/FileCategory.md +1 -1
  44. package/docs/api/interfaces/AggregateConfig.md +1 -1
  45. package/docs/api/interfaces/ButtonProps.md +1 -1
  46. package/docs/api/interfaces/CardProps.md +1 -1
  47. package/docs/api/interfaces/ColorPalette.md +1 -1
  48. package/docs/api/interfaces/ColorShade.md +1 -1
  49. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  50. package/docs/api/interfaces/DataRecord.md +1 -1
  51. package/docs/api/interfaces/DataTableAction.md +1 -1
  52. package/docs/api/interfaces/DataTableColumn.md +1 -1
  53. package/docs/api/interfaces/DataTableProps.md +1 -1
  54. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  55. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  56. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  57. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  58. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  59. package/docs/api/interfaces/FileMetadata.md +1 -1
  60. package/docs/api/interfaces/FileReference.md +1 -1
  61. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  62. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  63. package/docs/api/interfaces/FileUploadProps.md +1 -1
  64. package/docs/api/interfaces/FooterProps.md +1 -1
  65. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  66. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  67. package/docs/api/interfaces/InputProps.md +1 -1
  68. package/docs/api/interfaces/LabelProps.md +1 -1
  69. package/docs/api/interfaces/LoginFormProps.md +1 -1
  70. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  71. package/docs/api/interfaces/NavigationContextType.md +1 -1
  72. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  73. package/docs/api/interfaces/NavigationItem.md +1 -1
  74. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  75. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  76. package/docs/api/interfaces/Organisation.md +1 -1
  77. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  78. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  79. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  80. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  81. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  82. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  83. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  84. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  85. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  86. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  87. package/docs/api/interfaces/PaletteData.md +1 -1
  88. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  89. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  90. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  91. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  92. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  93. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  94. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  95. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  96. package/docs/api/interfaces/RBACConfig.md +1 -1
  97. package/docs/api/interfaces/RBACLogger.md +1 -1
  98. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  99. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  100. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  101. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  102. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  103. package/docs/api/interfaces/RouteConfig.md +1 -1
  104. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  105. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  106. package/docs/api/interfaces/StorageConfig.md +1 -1
  107. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  108. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  109. package/docs/api/interfaces/StorageListOptions.md +1 -1
  110. package/docs/api/interfaces/StorageListResult.md +1 -1
  111. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  112. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  113. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  114. package/docs/api/interfaces/StyleImport.md +1 -1
  115. package/docs/api/interfaces/SwitchProps.md +1 -1
  116. package/docs/api/interfaces/ToastActionElement.md +1 -1
  117. package/docs/api/interfaces/ToastProps.md +1 -1
  118. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  119. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  120. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  121. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  122. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  123. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  124. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  125. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  126. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  127. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  128. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  129. package/docs/api/interfaces/UserEventAccess.md +1 -1
  130. package/docs/api/interfaces/UserMenuProps.md +1 -1
  131. package/docs/api/interfaces/UserProfile.md +1 -1
  132. package/docs/api/modules.md +2 -2
  133. package/package.json +1 -1
  134. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +697 -0
  135. package/src/components/DataTable/components/DataTableCore.tsx +5 -0
  136. package/src/components/DataTable/components/EditableRow.tsx +9 -18
  137. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +616 -9
  138. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +1004 -0
  139. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +612 -0
  140. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +266 -0
  141. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +455 -1
  142. package/src/components/Toast/Toast.tsx +1 -1
  143. package/src/hooks/__tests__/index.unit.test.ts +223 -0
  144. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +748 -0
  145. package/src/hooks/__tests__/useEvents.unit.test.ts +251 -0
  146. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +1060 -0
  147. package/src/hooks/__tests__/useFileUrl.unit.test.ts +958 -0
  148. package/src/hooks/__tests__/useFocusManagement.unit.test.ts +19 -9
  149. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +540 -1
  150. package/src/hooks/__tests__/useIsMobile.unit.test.ts +205 -5
  151. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +616 -1
  152. package/src/hooks/__tests__/useOrganisations.unit.test.ts +369 -0
  153. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +661 -0
  154. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +2 -0
  155. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +371 -0
  156. package/src/hooks/__tests__/useToast.unit.test.tsx +449 -30
  157. package/src/hooks/useSecureDataAccess.test.ts +1 -0
  158. package/src/hooks/useToast.ts +4 -4
  159. package/src/rbac/audit-enhanced.ts +339 -0
  160. package/src/services/EventService.ts +1 -0
  161. package/src/services/__tests__/AuthService.test.ts +473 -0
  162. package/src/services/__tests__/EventService.test.ts +390 -0
  163. package/src/services/__tests__/InactivityService.test.ts +217 -0
  164. package/src/services/__tests__/OrganisationService.test.ts +371 -0
  165. package/src/styles/core.css +1 -0
  166. package/dist/chunk-2GJ5GL77.js.map +0 -1
  167. package/dist/chunk-2LM4QQGH.js.map +0 -1
  168. package/dist/chunk-KA3PSVNV.js.map +0 -1
  169. package/dist/chunk-UKZWNQMB.js.map +0 -1
  170. package/src/components/DataTable/utils/debugTools.ts +0 -609
  171. package/src/rbac/testing/index.tsx +0 -340
  172. /package/dist/{DataTable-ZOAKQ3SU.js.map → DataTable-DGZDJUYM.js.map} +0 -0
  173. /package/dist/{UnifiedAuthProvider-YFN7YGVN.js.map → UnifiedAuthProvider-UACKFATV.js.map} +0 -0
  174. /package/dist/{chunk-7OTQLFVI.js.map → chunk-B4GZ2BXO.js.map} +0 -0
  175. /package/dist/{chunk-LFS45U62.js.map → chunk-CGURJ27Z.js.map} +0 -0
  176. /package/dist/{chunk-PHDAXDHB.js.map → chunk-D6BOFXYR.js.map} +0 -0
  177. /package/dist/{chunk-P3PUOL6B.js.map → chunk-FKFHZUGF.js.map} +0 -0
  178. /package/dist/{chunk-O3FTRYEU.js.map → chunk-NZ32EONV.js.map} +0 -0
  179. /package/dist/{chunk-ECOVPXYS.js.map → chunk-RIEJGKD3.js.map} +0 -0
  180. /package/dist/{chunk-HIWXXDXO.js.map → chunk-TDNI6ZWL.js.map} +0 -0
  181. /package/dist/{chunk-VN3OOE35.js.map → chunk-ZYJ6O5CA.js.map} +0 -0
@@ -0,0 +1,251 @@
1
+ /**
2
+ * @file useEvents Hook Unit Tests
3
+ * @package @jmruthers/pace-core
4
+ * @module Hooks/__tests__/useEvents
5
+ * @since 0.1.0
6
+ *
7
+ * Comprehensive tests for the useEvents hook covering all critical functionality.
8
+ */
9
+
10
+ import { renderHook, act } from '@testing-library/react';
11
+ import { vi, describe, it, expect, beforeEach } from 'vitest';
12
+ import { useEvents } from '../useEvents';
13
+ import { Event } from '../../types/unified';
14
+
15
+ // Mock useEventService
16
+ const mockEventService = {
17
+ getEvents: vi.fn(() => []),
18
+ getSelectedEvent: vi.fn(() => null),
19
+ isLoading: vi.fn(() => false),
20
+ getError: vi.fn(() => null),
21
+ setSelectedEvent: vi.fn(),
22
+ refreshEvents: vi.fn().mockResolvedValue(undefined),
23
+ subscribe: vi.fn(() => vi.fn()), // Returns unsubscribe function
24
+ };
25
+
26
+ vi.mock('../services/useEventService', () => ({
27
+ useEventService: vi.fn(() => mockEventService),
28
+ }));
29
+
30
+ import { useEventService } from '../services/useEventService';
31
+
32
+ describe('useEvents', () => {
33
+ beforeEach(() => {
34
+ vi.clearAllMocks();
35
+ mockEventService.getEvents.mockReturnValue([]);
36
+ mockEventService.getSelectedEvent.mockReturnValue(null);
37
+ mockEventService.isLoading.mockReturnValue(false);
38
+ mockEventService.getError.mockReturnValue(null);
39
+ mockEventService.refreshEvents.mockResolvedValue(undefined);
40
+ });
41
+
42
+ describe('Initialization', () => {
43
+ it('returns event context with default values', () => {
44
+ const { result } = renderHook(() => useEvents());
45
+
46
+ expect(result.current.events).toEqual([]);
47
+ expect(result.current.selectedEvent).toBeNull();
48
+ expect(result.current.isLoading).toBe(false);
49
+ expect(result.current.error).toBeNull();
50
+ expect(typeof result.current.setSelectedEvent).toBe('function');
51
+ expect(typeof result.current.refreshEvents).toBe('function');
52
+ });
53
+
54
+ it('calls useEventService to get event service', () => {
55
+ const useEventServiceMock = vi.mocked(useEventService);
56
+
57
+ renderHook(() => useEvents());
58
+
59
+ expect(useEventServiceMock).toHaveBeenCalled();
60
+ });
61
+ });
62
+
63
+ describe('Event State Access', () => {
64
+ it('returns events from event service', () => {
65
+ const mockEvents: Event[] = [
66
+ {
67
+ id: 'event-1',
68
+ event_id: 'event-1',
69
+ event_name: 'Test Event 1',
70
+ event_date: '2025-01-01T00:00:00Z',
71
+ event_venue: 'Test Venue',
72
+ event_participants: 100,
73
+ event_colours: '#FF0000',
74
+ event_logo: '',
75
+ organisation_id: 'org-1',
76
+ is_visible: true,
77
+ name: 'Test Event 1',
78
+ start_date: '2025-01-01T00:00:00Z',
79
+ },
80
+ {
81
+ id: 'event-2',
82
+ event_id: 'event-2',
83
+ event_name: 'Test Event 2',
84
+ event_date: '2025-02-01T00:00:00Z',
85
+ event_venue: 'Test Venue 2',
86
+ event_participants: 200,
87
+ event_colours: '#00FF00',
88
+ event_logo: '',
89
+ organisation_id: 'org-1',
90
+ is_visible: true,
91
+ name: 'Test Event 2',
92
+ start_date: '2025-02-01T00:00:00Z',
93
+ },
94
+ ];
95
+
96
+ mockEventService.getEvents.mockReturnValue(mockEvents);
97
+
98
+ const { result } = renderHook(() => useEvents());
99
+
100
+ expect(result.current.events).toEqual(mockEvents);
101
+ expect(result.current.events).toHaveLength(2);
102
+ });
103
+
104
+ it('returns selected event from event service', () => {
105
+ const mockSelectedEvent: Event = {
106
+ id: 'event-1',
107
+ event_id: 'event-1',
108
+ event_name: 'Selected Event',
109
+ event_date: '2025-01-01T00:00:00Z',
110
+ event_venue: 'Test Venue',
111
+ event_participants: 100,
112
+ event_colours: '#FF0000',
113
+ event_logo: '',
114
+ organisation_id: 'org-1',
115
+ is_visible: true,
116
+ name: 'Selected Event',
117
+ start_date: '2025-01-01T00:00:00Z',
118
+ };
119
+
120
+ mockEventService.getSelectedEvent.mockReturnValue(mockSelectedEvent);
121
+
122
+ const { result } = renderHook(() => useEvents());
123
+
124
+ expect(result.current.selectedEvent).toEqual(mockSelectedEvent);
125
+ });
126
+
127
+ it('returns loading state from event service', () => {
128
+ mockEventService.isLoading.mockReturnValue(true);
129
+
130
+ const { result } = renderHook(() => useEvents());
131
+
132
+ expect(result.current.isLoading).toBe(true);
133
+ });
134
+
135
+ it('returns error from event service', () => {
136
+ const mockError = new Error('Failed to load events');
137
+ mockEventService.getError.mockReturnValue(mockError);
138
+
139
+ const { result } = renderHook(() => useEvents());
140
+
141
+ expect(result.current.error).toEqual(mockError);
142
+ });
143
+ });
144
+
145
+ describe('Event Selection', () => {
146
+ it('calls setSelectedEvent on event service when setSelectedEvent is called', () => {
147
+ const mockEvent: Event = {
148
+ id: 'event-1',
149
+ event_id: 'event-1',
150
+ event_name: 'Test Event',
151
+ event_date: '2025-01-01T00:00:00Z',
152
+ event_venue: 'Test Venue',
153
+ event_participants: 100,
154
+ event_colours: '#FF0000',
155
+ event_logo: '',
156
+ organisation_id: 'org-1',
157
+ is_visible: true,
158
+ name: 'Test Event',
159
+ start_date: '2025-01-01T00:00:00Z',
160
+ };
161
+
162
+ const { result } = renderHook(() => useEvents());
163
+
164
+ act(() => {
165
+ result.current.setSelectedEvent(mockEvent);
166
+ });
167
+
168
+ expect(mockEventService.setSelectedEvent).toHaveBeenCalledWith(mockEvent);
169
+ expect(mockEventService.setSelectedEvent).toHaveBeenCalledTimes(1);
170
+ });
171
+
172
+ it('calls setSelectedEvent with null when clearing selection', () => {
173
+ const { result } = renderHook(() => useEvents());
174
+
175
+ act(() => {
176
+ result.current.setSelectedEvent(null);
177
+ });
178
+
179
+ expect(mockEventService.setSelectedEvent).toHaveBeenCalledWith(null);
180
+ expect(mockEventService.setSelectedEvent).toHaveBeenCalledTimes(1);
181
+ });
182
+ });
183
+
184
+ describe('Event Refresh', () => {
185
+ it('calls refreshEvents on event service when refreshEvents is called', async () => {
186
+ const { result } = renderHook(() => useEvents());
187
+
188
+ await act(async () => {
189
+ await result.current.refreshEvents();
190
+ });
191
+
192
+ expect(mockEventService.refreshEvents).toHaveBeenCalledTimes(1);
193
+ });
194
+
195
+ it('handles refreshEvents promise resolution', async () => {
196
+ mockEventService.refreshEvents.mockResolvedValue(undefined);
197
+
198
+ const { result } = renderHook(() => useEvents());
199
+
200
+ await act(async () => {
201
+ await expect(result.current.refreshEvents()).resolves.toBeUndefined();
202
+ });
203
+ });
204
+
205
+ it('handles refreshEvents promise rejection', async () => {
206
+ const mockError = new Error('Refresh failed');
207
+ mockEventService.refreshEvents.mockRejectedValue(mockError);
208
+
209
+ const { result } = renderHook(() => useEvents());
210
+
211
+ await act(async () => {
212
+ await expect(result.current.refreshEvents()).rejects.toThrow('Refresh failed');
213
+ });
214
+ });
215
+ });
216
+
217
+ describe('Reactive Updates', () => {
218
+ it('updates when event service state changes', () => {
219
+ const mockEvents: Event[] = [
220
+ {
221
+ id: 'event-1',
222
+ event_id: 'event-1',
223
+ event_name: 'Test Event',
224
+ event_date: '2025-01-01T00:00:00Z',
225
+ event_venue: 'Test Venue',
226
+ event_participants: 100,
227
+ event_colours: '#FF0000',
228
+ event_logo: '',
229
+ organisation_id: 'org-1',
230
+ is_visible: true,
231
+ name: 'Test Event',
232
+ start_date: '2025-01-01T00:00:00Z',
233
+ },
234
+ ];
235
+
236
+ const { result, rerender } = renderHook(() => useEvents());
237
+
238
+ // Initial state
239
+ expect(result.current.events).toEqual([]);
240
+
241
+ // Update mock and rerender
242
+ mockEventService.getEvents.mockReturnValue(mockEvents);
243
+ rerender();
244
+
245
+ // Note: In real usage, the subscription would trigger updates
246
+ // This test verifies the hook structure
247
+ expect(mockEventService.getEvents).toHaveBeenCalled();
248
+ });
249
+ });
250
+ });
251
+