@jmruthers/pace-core 0.5.86 → 0.5.88

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 (248) hide show
  1. package/dist/{AuthService-Df3IozMG.d.ts → AuthService-DcTI5Ov4.d.ts} +9 -0
  2. package/dist/{DataTable-DKGTBLWT.js → DataTable-PWBMKMOG.js} +8 -8
  3. package/dist/{PublicLoadingSpinner-CnUaz0vG.d.ts → PublicLoadingSpinner-BQXD1fbO.d.ts} +161 -131
  4. package/dist/{UnifiedAuthProvider-K2IZAY5F.js → UnifiedAuthProvider-5D3HEQND.js} +4 -4
  5. package/dist/{UnifiedAuthProvider-B391Aqum.d.ts → UnifiedAuthProvider-BVKmQd9u.d.ts} +4 -0
  6. package/dist/auth-DReDSLq9.d.ts +16 -0
  7. package/dist/{chunk-CBSD3BZ3.js → chunk-3RZBKQ5Y.js} +2 -6
  8. package/dist/{chunk-CBSD3BZ3.js.map → chunk-3RZBKQ5Y.js.map} +1 -1
  9. package/dist/{chunk-NTW3KGS4.js → chunk-6UHXQH7P.js} +5 -5
  10. package/dist/{chunk-YVUZWLQG.js → chunk-AQGF5OG7.js} +3 -3
  11. package/dist/{chunk-CVMVPYAL.js → chunk-BDZUMRBD.js} +3 -5
  12. package/dist/chunk-BDZUMRBD.js.map +1 -0
  13. package/dist/{chunk-QCCJ3P4W.js → chunk-BNXBJOGL.js} +5 -5
  14. package/dist/{chunk-IBMPGOCN.js → chunk-CJIZS3UE.js} +1430 -783
  15. package/dist/chunk-CJIZS3UE.js.map +1 -0
  16. package/dist/{chunk-S3JKDMD5.js → chunk-CXKMRKRF.js} +4 -4
  17. package/dist/{chunk-5BN3YGNK.js → chunk-DP5X5ORK.js} +217 -27
  18. package/dist/chunk-DP5X5ORK.js.map +1 -0
  19. package/dist/{chunk-KUYWZVR2.js → chunk-H3P2RGKZ.js} +353 -9
  20. package/dist/chunk-H3P2RGKZ.js.map +1 -0
  21. package/dist/{chunk-RIXPZJUB.js → chunk-KTPG5VCH.js} +2 -2
  22. package/dist/{chunk-YCKPEMJA.js → chunk-QPCAGLUS.js} +2 -3
  23. package/dist/chunk-QPCAGLUS.js.map +1 -0
  24. package/dist/{chunk-WUXCWRL6.js → chunk-XJ2HZOBU.js} +6 -1
  25. package/dist/chunk-XJ2HZOBU.js.map +1 -0
  26. package/dist/{chunk-V5SWX6KL.js → chunk-XXVM53P4.js} +4 -4
  27. package/dist/{chunk-I2VVV5PQ.js → chunk-YY4YYM3E.js} +2 -2
  28. package/dist/components.d.ts +6 -55
  29. package/dist/components.js +25 -206
  30. package/dist/components.js.map +1 -1
  31. package/dist/{file-reference-9xUOnwyt.d.ts → file-reference-C9isKNPn.d.ts} +67 -2
  32. package/dist/hooks.js +10 -9
  33. package/dist/hooks.js.map +1 -1
  34. package/dist/index.d.ts +152 -26
  35. package/dist/index.js +65 -195
  36. package/dist/index.js.map +1 -1
  37. package/dist/providers.d.ts +5 -3
  38. package/dist/providers.js +3 -3
  39. package/dist/rbac/index.js +8 -8
  40. package/dist/types.d.ts +2 -1
  41. package/dist/types.js +3 -3
  42. package/dist/utils.js +2 -2
  43. package/docs/DOCUMENTATION_AUDIT.md +6 -6
  44. package/docs/DOCUMENTATION_STANDARD.md +137 -0
  45. package/docs/README.md +1 -1
  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 +83 -40
  60. package/docs/api/enums/FileCategory.md +56 -1
  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/DataRecord.md +1 -1
  68. package/docs/api/interfaces/DataTableAction.md +1 -1
  69. package/docs/api/interfaces/DataTableColumn.md +1 -1
  70. package/docs/api/interfaces/DataTableProps.md +1 -1
  71. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  72. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  73. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  74. package/docs/api/interfaces/EventLogoProps.md +11 -11
  75. package/docs/api/interfaces/FileDisplayProps.md +10 -10
  76. package/docs/api/interfaces/FileMetadata.md +1 -1
  77. package/docs/api/interfaces/FileReference.md +1 -1
  78. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  79. package/docs/api/interfaces/FileUploadOptions.md +8 -8
  80. package/docs/api/interfaces/FileUploadProps.md +137 -42
  81. package/docs/api/interfaces/FooterProps.md +1 -1
  82. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  83. package/docs/api/interfaces/InputProps.md +1 -1
  84. package/docs/api/interfaces/LabelProps.md +1 -1
  85. package/docs/api/interfaces/LoginFormProps.md +1 -1
  86. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  87. package/docs/api/interfaces/NavigationContextType.md +1 -1
  88. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  89. package/docs/api/interfaces/NavigationItem.md +1 -1
  90. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  91. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  92. package/docs/api/interfaces/Organisation.md +1 -1
  93. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  94. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  95. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  96. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  97. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  98. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  99. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  100. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  101. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  102. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  103. package/docs/api/interfaces/PaletteData.md +1 -1
  104. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  105. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  106. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  107. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  108. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  109. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  110. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  111. package/docs/api/interfaces/RBACConfig.md +1 -1
  112. package/docs/api/interfaces/RBACLogger.md +1 -1
  113. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  114. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  115. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  116. package/docs/api/interfaces/RouteConfig.md +1 -1
  117. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  118. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  119. package/docs/api/interfaces/StorageConfig.md +1 -1
  120. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  121. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  122. package/docs/api/interfaces/StorageListOptions.md +1 -1
  123. package/docs/api/interfaces/StorageListResult.md +1 -1
  124. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  125. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  126. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  127. package/docs/api/interfaces/StyleImport.md +1 -1
  128. package/docs/api/interfaces/SwitchProps.md +1 -1
  129. package/docs/api/interfaces/ToastActionElement.md +1 -1
  130. package/docs/api/interfaces/ToastProps.md +1 -1
  131. package/docs/api/interfaces/UnifiedAuthContextType.md +83 -50
  132. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  133. package/docs/api/interfaces/UseEventLogoOptions.md +74 -0
  134. package/docs/api/interfaces/UseEventLogoReturn.md +81 -0
  135. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  136. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  137. package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
  138. package/docs/api/interfaces/UsePublicEventLogoReturn.md +6 -6
  139. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  140. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  141. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  142. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  143. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  144. package/docs/api/interfaces/UserEventAccess.md +11 -11
  145. package/docs/api/interfaces/UserMenuProps.md +1 -1
  146. package/docs/api/interfaces/UserProfile.md +1 -1
  147. package/docs/api/modules.md +292 -97
  148. package/docs/api-reference/components.md +1 -18
  149. package/docs/api-reference/hooks.md +1 -4
  150. package/docs/best-practices/testing.md +2 -0
  151. package/docs/documentation-index.md +1 -1
  152. package/docs/getting-started/faq.md +1 -1
  153. package/docs/implementation-guides/file-reference-system.md +592 -58
  154. package/docs/implementation-guides/file-upload-storage.md +137 -73
  155. package/docs/rbac/super-admin-guide.md +18 -70
  156. package/docs/testing/README.md +2 -0
  157. package/package.json +1 -1
  158. package/src/__tests__/TEST_STANDARD.md +674 -0
  159. package/src/__tests__/helpers/test-utils.tsx +3 -2
  160. package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx.skip → DataTable.comprehensive.test.tsx} +17 -18
  161. package/src/components/DataTable/__tests__/{DataTable.test.tsx.skip → DataTable.test.tsx} +14 -22
  162. package/src/components/DataTable/__tests__/{ssr.strict-mode.test.tsx.skip → ssr.strict-mode.test.tsx} +42 -47
  163. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +1 -1
  164. package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +13 -4
  165. package/src/components/DataTable/utils/__tests__/COVERAGE_NOTE.md +1 -1
  166. package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +10 -6
  167. package/src/components/DataTable/utils/performanceUtils.ts +12 -3
  168. package/src/components/FileDisplay/FileDisplay.test.tsx +257 -0
  169. package/src/components/{FileDisplay.tsx → FileDisplay/FileDisplay.tsx} +111 -10
  170. package/src/components/FileDisplay/index.tsx +4 -0
  171. package/src/components/FileUpload/FileUpload.test.tsx +171 -621
  172. package/src/components/FileUpload/FileUpload.tsx +512 -168
  173. package/src/components/FileUpload/index.tsx +4 -0
  174. package/src/components/Progress/Progress.test.tsx +38 -0
  175. package/src/components/PublicLayout/EventLogo.tsx +220 -39
  176. package/src/components/PublicLayout/PublicPageProvider.tsx +1 -1
  177. package/src/components/Select/Select.test.tsx +1 -1
  178. package/src/components/SessionRestorationLoader.tsx +48 -0
  179. package/src/components/Toast/Toast.tsx +13 -8
  180. package/src/components/index.ts +16 -16
  181. package/src/hooks/__tests__/ServiceHooks.test.tsx +615 -0
  182. package/src/hooks/public/usePublicEventLogo.ts +17 -7
  183. package/src/hooks/useDataTablePerformance.ts +4 -0
  184. package/src/hooks/useEventLogo.ts +316 -0
  185. package/src/hooks/useEvents.ts +0 -5
  186. package/src/hooks/useFileReference.test.ts +659 -0
  187. package/src/hooks/useFileReference.ts +207 -3
  188. package/src/hooks/useSessionRestoration.ts +64 -0
  189. package/src/index.ts +17 -5
  190. package/src/providers/{UnifiedAuthProvider.test.simple.tsx → UnifiedAuthProvider.smoke.test.tsx} +81 -60
  191. package/src/providers/services/AuthServiceProvider.tsx +27 -3
  192. package/src/providers/services/UnifiedAuthProvider.tsx +34 -5
  193. package/src/rbac/{engine.test.simple.ts → RBACEngine.smoke.test.ts} +17 -12
  194. package/src/services/AuthService.ts +142 -20
  195. package/src/services/EventService.ts +0 -4
  196. package/src/types/auth.ts +15 -0
  197. package/src/types/file-reference.ts +73 -1
  198. package/src/types/index.ts +1 -0
  199. package/src/utils/__tests__/organisationContext.unit.test.ts +2 -4
  200. package/src/utils/appNameResolver.simple.test.ts +99 -29
  201. package/src/utils/file-reference.test.ts +535 -0
  202. package/src/utils/file-reference.ts +200 -30
  203. package/src/utils/organisationContext.test.ts +5 -19
  204. package/src/utils/organisationContext.ts +3 -5
  205. package/src/utils/storage/README.md +269 -262
  206. package/src/utils/storage/config.ts +9 -0
  207. package/src/utils/storage/helpers.test.ts +631 -0
  208. package/src/utils/storage/helpers.ts +112 -14
  209. package/src/utils/storage/index.ts +3 -0
  210. package/src/validation/__tests__/sanitization.unit.test.ts +1 -1
  211. package/src/validation/__tests__/schemaUtils.unit.test.ts +1 -1
  212. package/src/validation/__tests__/user.unit.test.ts +1 -1
  213. package/dist/chunk-5BN3YGNK.js.map +0 -1
  214. package/dist/chunk-CVMVPYAL.js.map +0 -1
  215. package/dist/chunk-IBMPGOCN.js.map +0 -1
  216. package/dist/chunk-KUYWZVR2.js.map +0 -1
  217. package/dist/chunk-WUXCWRL6.js.map +0 -1
  218. package/dist/chunk-YCKPEMJA.js.map +0 -1
  219. package/docs/CONTENT_AUDIT_REPORT.md +0 -253
  220. package/docs/STYLE_GUIDE.md +0 -37
  221. package/examples/RBAC/__tests__/PermissionExample.test.tsx +0 -150
  222. package/examples/public-pages/__tests__/PublicPageUsageExample.test.tsx +0 -159
  223. package/src/__tests__/TEST_GUIDE_CURSOR.md +0 -1605
  224. package/src/__tests__/TEST_GUIDE_HUMAN.md +0 -103
  225. package/src/components/FileUpload/FileUpload.example.tsx +0 -218
  226. package/src/components/FileUpload/index.ts +0 -6
  227. package/src/components/FileUpload.tsx +0 -176
  228. package/src/components/Progress/index.ts +0 -3
  229. package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +0 -666
  230. package/src/components/SuperAdminGuard.tsx +0 -116
  231. package/src/components/__tests__/FileDisplay.test.tsx +0 -575
  232. package/src/components/__tests__/FileUpload.test.tsx +0 -446
  233. package/src/components/__tests__/SuperAdminGuard.test.tsx +0 -627
  234. package/src/components/examples/PermissionExample.tsx +0 -173
  235. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +0 -583
  236. package/src/hooks/__tests__/usePublicEventLogo.unit.test.ts +0 -640
  237. package/src/types/__tests__/file-reference.test.ts +0 -447
  238. package/src/utils/__tests__/file-reference.test.ts +0 -383
  239. /package/dist/{DataTable-DKGTBLWT.js.map → DataTable-PWBMKMOG.js.map} +0 -0
  240. /package/dist/{UnifiedAuthProvider-K2IZAY5F.js.map → UnifiedAuthProvider-5D3HEQND.js.map} +0 -0
  241. /package/dist/{chunk-NTW3KGS4.js.map → chunk-6UHXQH7P.js.map} +0 -0
  242. /package/dist/{chunk-YVUZWLQG.js.map → chunk-AQGF5OG7.js.map} +0 -0
  243. /package/dist/{chunk-QCCJ3P4W.js.map → chunk-BNXBJOGL.js.map} +0 -0
  244. /package/dist/{chunk-S3JKDMD5.js.map → chunk-CXKMRKRF.js.map} +0 -0
  245. /package/dist/{chunk-RIXPZJUB.js.map → chunk-KTPG5VCH.js.map} +0 -0
  246. /package/dist/{chunk-V5SWX6KL.js.map → chunk-XXVM53P4.js.map} +0 -0
  247. /package/dist/{chunk-I2VVV5PQ.js.map → chunk-YY4YYM3E.js.map} +0 -0
  248. /package/src/providers/{OrganisationProvider.test.simple.tsx → OrganisationProvider.context.test.tsx} +0 -0
@@ -1,666 +0,0 @@
1
- /**
2
- * @file EventLogo Component Tests
3
- * @package @jmruthers/pace-core
4
- * @module Components/PublicLayout/__tests__
5
- * @since 1.0.0
6
- */
7
-
8
- import React from 'react';
9
- import { render, screen, fireEvent } from '@testing-library/react';
10
- import { describe, it, expect, vi, beforeEach } from 'vitest';
11
- import {
12
- EventLogo,
13
- EventLogoCompact,
14
- EventLogoLarge
15
- } from '../EventLogo';
16
-
17
- // Mock the usePublicEventLogo hook
18
- const mockUsePublicEventLogo = vi.fn();
19
-
20
- // Mock the usePublicPageContext hook
21
- const mockUsePublicPageContext = vi.fn();
22
-
23
- // Mock the UnifiedAuthProvider
24
- const mockUseUnifiedAuth = vi.fn();
25
-
26
- vi.mock('../../../hooks/public/usePublicEventLogo', () => ({
27
- usePublicEventLogo: vi.fn()
28
- }));
29
-
30
- vi.mock('../PublicPageProvider', () => ({
31
- usePublicPageContext: () => mockUsePublicPageContext()
32
- }));
33
-
34
- vi.mock('../../../providers/UnifiedAuthProvider', () => ({
35
- useUnifiedAuth: () => mockUseUnifiedAuth()
36
- }));
37
-
38
- describe('[component] EventLogo', () => {
39
- beforeEach(async () => {
40
- vi.clearAllMocks();
41
-
42
- // Default mock implementations
43
- mockUsePublicPageContext.mockReturnValue({
44
- isPublicPage: false,
45
- supabase: { from: vi.fn() }
46
- });
47
-
48
- mockUsePublicEventLogo.mockReturnValue({
49
- logoUrl: null,
50
- fallbackText: 'TE',
51
- isLoading: false,
52
- error: null
53
- });
54
-
55
- // Set up the mocked hook
56
- const { usePublicEventLogo } = await import('../../../hooks/public/usePublicEventLogo');
57
- vi.mocked(usePublicEventLogo).mockImplementation(mockUsePublicEventLogo);
58
- });
59
-
60
- describe('Rendering', () => {
61
- it('renders with basic props', () => {
62
- render(
63
- <EventLogo
64
- eventId="event-123"
65
- eventName="Test Event"
66
- organisationId="org-123"
67
- />
68
- );
69
-
70
- expect(screen.getByText('TE')).toBeInTheDocument();
71
- });
72
-
73
- it('renders with custom className', () => {
74
- const { container } = render(
75
- <EventLogo
76
- eventId="event-123"
77
- eventName="Test Event"
78
- organisationId="org-123"
79
- className="custom-logo-class"
80
- />
81
- );
82
-
83
- const logo = container.firstChild as HTMLElement;
84
- expect(logo).toHaveClass('custom-logo-class');
85
- });
86
-
87
- it('renders with custom size', () => {
88
- const { container } = render(
89
- <EventLogo
90
- eventId="event-123"
91
- eventName="Test Event"
92
- organisationId="org-123"
93
- size="lg"
94
- />
95
- );
96
-
97
- const logo = container.firstChild as HTMLElement;
98
- expect(logo).toHaveClass('h-12', 'w-12', 'text-lg');
99
- });
100
- });
101
-
102
- describe('Size Variants', () => {
103
- it('renders with extra small size', () => {
104
- const { container } = render(
105
- <EventLogo
106
- eventId="event-123"
107
- eventName="Test Event"
108
- organisationId="org-123"
109
- size="xs"
110
- />
111
- );
112
-
113
- const logo = container.firstChild as HTMLElement;
114
- expect(logo).toHaveClass('h-4', 'w-4', 'text-xs');
115
- });
116
-
117
- it('renders with small size', () => {
118
- const { container } = render(
119
- <EventLogo
120
- eventId="event-123"
121
- eventName="Test Event"
122
- organisationId="org-123"
123
- size="sm"
124
- />
125
- );
126
-
127
- const logo = container.firstChild as HTMLElement;
128
- expect(logo).toHaveClass('h-6', 'w-6', 'text-sm');
129
- });
130
-
131
- it('renders with medium size by default', () => {
132
- const { container } = render(
133
- <EventLogo
134
- eventId="event-123"
135
- eventName="Test Event"
136
- organisationId="org-123"
137
- />
138
- );
139
-
140
- const logo = container.firstChild as HTMLElement;
141
- expect(logo).toHaveClass('h-8', 'w-8', 'text-base');
142
- });
143
-
144
- it('renders with large size', () => {
145
- const { container } = render(
146
- <EventLogo
147
- eventId="event-123"
148
- eventName="Test Event"
149
- organisationId="org-123"
150
- size="lg"
151
- />
152
- );
153
-
154
- const logo = container.firstChild as HTMLElement;
155
- expect(logo).toHaveClass('h-12', 'w-12', 'text-lg');
156
- });
157
-
158
- it('renders with extra large size', () => {
159
- const { container } = render(
160
- <EventLogo
161
- eventId="event-123"
162
- eventName="Test Event"
163
- organisationId="org-123"
164
- size="xl"
165
- />
166
- );
167
-
168
- const logo = container.firstChild as HTMLElement;
169
- expect(logo).toHaveClass('h-16', 'w-16', 'text-xl');
170
- });
171
-
172
- it('renders with 2xl size', () => {
173
- const { container } = render(
174
- <EventLogo
175
- eventId="event-123"
176
- eventName="Test Event"
177
- organisationId="org-123"
178
- size="2xl"
179
- />
180
- );
181
-
182
- const logo = container.firstChild as HTMLElement;
183
- expect(logo).toHaveClass('h-20', 'w-20', 'text-2xl');
184
- });
185
- });
186
-
187
- describe('Fallback Text Generation', () => {
188
- it('generates fallback text from event name', () => {
189
- render(
190
- <EventLogo
191
- eventId="event-123"
192
- eventName="Test Event"
193
- organisationId="org-123"
194
- />
195
- );
196
-
197
- expect(screen.getByText('TE')).toBeInTheDocument();
198
- });
199
-
200
- it('generates fallback text from single word event name', () => {
201
- mockUsePublicEventLogo.mockReturnValue({
202
- logoUrl: null,
203
- fallbackText: 'T',
204
- isLoading: false,
205
- error: null
206
- });
207
-
208
- render(
209
- <EventLogo
210
- eventId="event-123"
211
- eventName="Test"
212
- organisationId="org-123"
213
- />
214
- );
215
-
216
- expect(screen.getByText('T')).toBeInTheDocument();
217
- });
218
-
219
- it('generates fallback text from multi-word event name', () => {
220
- mockUsePublicEventLogo.mockReturnValue({
221
- logoUrl: null,
222
- fallbackText: 'TEC',
223
- isLoading: false,
224
- error: null
225
- });
226
-
227
- render(
228
- <EventLogo
229
- eventId="event-123"
230
- eventName="Test Event Conference"
231
- organisationId="org-123"
232
- />
233
- );
234
-
235
- expect(screen.getByText('TEC')).toBeInTheDocument();
236
- });
237
-
238
- it('handles empty event name', () => {
239
- mockUsePublicEventLogo.mockReturnValue({
240
- logoUrl: null,
241
- fallbackText: 'EV',
242
- isLoading: false,
243
- error: null
244
- });
245
-
246
- render(
247
- <EventLogo
248
- eventId="event-123"
249
- eventName=""
250
- organisationId="org-123"
251
- />
252
- );
253
-
254
- expect(screen.getByText('EV')).toBeInTheDocument();
255
- });
256
- });
257
-
258
- describe('Logo Display', () => {
259
- it('renders actual logo when available', () => {
260
- mockUsePublicEventLogo.mockReturnValue({
261
- logoUrl: 'https://example.com/logo.png',
262
- fallbackText: 'TE',
263
- isLoading: false,
264
- error: null
265
- });
266
-
267
- render(
268
- <EventLogo
269
- eventId="event-123"
270
- eventName="Test Event"
271
- organisationId="org-123"
272
- />
273
- );
274
-
275
- const logo = screen.getByAltText('Test Event logo');
276
- expect(logo).toBeInTheDocument();
277
- expect(logo).toHaveAttribute('src', 'https://example.com/logo.png');
278
- });
279
-
280
- it('renders fallback when no logo available', () => {
281
- mockUsePublicEventLogo.mockReturnValue({
282
- logoUrl: null,
283
- fallbackText: 'TE',
284
- isLoading: false,
285
- error: null
286
- });
287
-
288
- render(
289
- <EventLogo
290
- eventId="event-123"
291
- eventName="Test Event"
292
- organisationId="org-123"
293
- />
294
- );
295
-
296
- expect(screen.getByText('TE')).toBeInTheDocument();
297
- expect(screen.queryByAltText('Test Event logo')).not.toBeInTheDocument();
298
- });
299
-
300
- it('handles image load error', () => {
301
- mockUsePublicEventLogo.mockReturnValue({
302
- logoUrl: 'https://example.com/logo.png',
303
- fallbackText: 'TE',
304
- isLoading: false,
305
- error: null
306
- });
307
-
308
- render(
309
- <EventLogo
310
- eventId="event-123"
311
- eventName="Test Event"
312
- organisationId="org-123"
313
- />
314
- );
315
-
316
- const logo = screen.getByAltText('Test Event logo');
317
-
318
- // Simulate image load error
319
- fireEvent.error(logo);
320
-
321
- // The image should be hidden and fallback should be shown
322
- expect(logo).toHaveStyle('display: none');
323
- });
324
- });
325
-
326
- describe('Loading States', () => {
327
- it('renders loading state', () => {
328
- mockUsePublicEventLogo.mockReturnValue({
329
- logoUrl: null,
330
- fallbackText: 'TE',
331
- isLoading: true,
332
- error: null
333
- });
334
-
335
- const { container } = render(
336
- <EventLogo
337
- eventId="event-123"
338
- eventName="Test Event"
339
- organisationId="org-123"
340
- />
341
- );
342
-
343
- const logo = container.firstChild as HTMLElement;
344
- expect(logo).toHaveClass('animate-pulse');
345
- });
346
-
347
- it('renders custom loading component', () => {
348
- const CustomLoading = () => <div data-testid="custom-loading">Loading...</div>;
349
-
350
- mockUsePublicEventLogo.mockReturnValue({
351
- logoUrl: null,
352
- fallbackText: 'TE',
353
- isLoading: true,
354
- error: null
355
- });
356
-
357
- render(
358
- <EventLogo
359
- eventId="event-123"
360
- eventName="Test Event"
361
- organisationId="org-123"
362
- loadingComponent={CustomLoading}
363
- />
364
- );
365
-
366
- expect(screen.getByTestId('custom-loading')).toBeInTheDocument();
367
- });
368
- });
369
-
370
- describe('Error States', () => {
371
- it('renders error state with fallback', () => {
372
- mockUsePublicEventLogo.mockReturnValue({
373
- logoUrl: null,
374
- fallbackText: 'TE',
375
- isLoading: false,
376
- error: new Error('Failed to load logo')
377
- });
378
-
379
- render(
380
- <EventLogo
381
- eventId="event-123"
382
- eventName="Test Event"
383
- organisationId="org-123"
384
- />
385
- );
386
-
387
- expect(screen.getByText('TE')).toBeInTheDocument();
388
- });
389
-
390
- it('renders custom error component', async () => {
391
- const CustomError = ({ error }: { error: Error }) => (
392
- <div data-testid="custom-error">Error: {error.message}</div>
393
- );
394
-
395
- // Set up the mock after beforeEach has run
396
- mockUsePublicEventLogo.mockReturnValue({
397
- logoUrl: null,
398
- fallbackText: 'TE',
399
- isLoading: false,
400
- error: new Error('Failed to load logo')
401
- });
402
-
403
- // Set up the mocked hook
404
- const { usePublicEventLogo } = await import('../../../hooks/public/usePublicEventLogo');
405
- vi.mocked(usePublicEventLogo).mockImplementation(mockUsePublicEventLogo);
406
-
407
- const { container } = render(
408
- <EventLogo
409
- eventId="event-123"
410
- eventName="Test Event"
411
- organisationId="550e8400-e29b-41d4-a716-446655440000"
412
- errorComponent={CustomError}
413
- />
414
- );
415
-
416
- expect(screen.getByTestId('custom-error')).toBeInTheDocument();
417
- expect(screen.getByText('Error: Failed to load logo')).toBeInTheDocument();
418
- });
419
-
420
- it('returns null when no fallback and error occurs', async () => {
421
- // Set up the mock after beforeEach has run
422
- mockUsePublicEventLogo.mockReturnValue({
423
- logoUrl: null,
424
- fallbackText: 'TE',
425
- isLoading: false,
426
- error: new Error('Failed to load logo')
427
- });
428
-
429
- // Set up the mocked hook
430
- const { usePublicEventLogo } = await import('../../../hooks/public/usePublicEventLogo');
431
- vi.mocked(usePublicEventLogo).mockImplementation(mockUsePublicEventLogo);
432
-
433
- const { container } = render(
434
- <EventLogo
435
- eventId="event-123"
436
- eventName="Test Event"
437
- organisationId="org-123"
438
- showFallback={false}
439
- />
440
- );
441
-
442
- expect(container.firstChild).toBeNull();
443
- });
444
- });
445
-
446
- describe('Context Awareness', () => {
447
- it('handles public page context', () => {
448
- mockUsePublicPageContext.mockReturnValue({
449
- isPublicPage: true,
450
- supabase: { from: vi.fn() }
451
- });
452
-
453
- render(
454
- <EventLogo
455
- eventId="event-123"
456
- eventName="Test Event"
457
- organisationId="org-123"
458
- />
459
- );
460
-
461
- expect(screen.getByText('TE')).toBeInTheDocument();
462
- });
463
-
464
- it('handles missing Supabase client', () => {
465
- mockUsePublicPageContext.mockReturnValue({
466
- isPublicPage: false,
467
- supabase: null
468
- });
469
-
470
- render(
471
- <EventLogo
472
- eventId="event-123"
473
- eventName="Test Event"
474
- organisationId="org-123"
475
- />
476
- );
477
-
478
- expect(screen.getByText('TE')).toBeInTheDocument();
479
- });
480
- });
481
-
482
- describe('Organisation ID Validation', () => {
483
- it('handles invalid organisation ID', () => {
484
- mockUsePublicEventLogo.mockReturnValue({
485
- logoUrl: null,
486
- fallbackText: 'TE',
487
- isLoading: false,
488
- error: null
489
- });
490
-
491
- render(
492
- <EventLogo
493
- eventId="event-123"
494
- eventName="Test Event"
495
- organisationId="invalid-id"
496
- />
497
- );
498
-
499
- expect(screen.getByText('TE')).toBeInTheDocument();
500
- });
501
-
502
- it('handles empty organisation ID', () => {
503
- mockUsePublicEventLogo.mockReturnValue({
504
- logoUrl: null,
505
- fallbackText: 'TE',
506
- isLoading: false,
507
- error: null
508
- });
509
-
510
- render(
511
- <EventLogo
512
- eventId="event-123"
513
- eventName="Test Event"
514
- organisationId=""
515
- />
516
- );
517
-
518
- expect(screen.getByText('TE')).toBeInTheDocument();
519
- });
520
- });
521
-
522
- describe('Accessibility', () => {
523
- it('has proper alt text for images', () => {
524
- mockUsePublicEventLogo.mockReturnValue({
525
- logoUrl: 'https://example.com/logo.png',
526
- fallbackText: 'TE',
527
- isLoading: false,
528
- error: null
529
- });
530
-
531
- render(
532
- <EventLogo
533
- eventId="event-123"
534
- eventName="Test Event"
535
- organisationId="org-123"
536
- />
537
- );
538
-
539
- const logo = screen.getByAltText('Test Event logo');
540
- expect(logo).toBeInTheDocument();
541
- });
542
-
543
- it('has proper title attribute for fallback', () => {
544
- mockUsePublicEventLogo.mockReturnValue({
545
- logoUrl: null,
546
- fallbackText: 'TE',
547
- isLoading: false,
548
- error: null
549
- });
550
-
551
- render(
552
- <EventLogo
553
- eventId="event-123"
554
- eventName="Test Event"
555
- organisationId="org-123"
556
- />
557
- );
558
-
559
- const fallback = screen.getByText('TE');
560
- expect(fallback).toHaveAttribute('title', 'Test Event logo (invalid organisation ID)');
561
- });
562
- });
563
-
564
- describe('Props Validation', () => {
565
- it('handles missing eventId prop gracefully', () => {
566
- // @ts-expect-error - Testing invalid props
567
- const { container } = render(
568
- <EventLogo
569
- eventName="Test Event"
570
- organisationId="org-123"
571
- />
572
- );
573
- expect(container.firstChild).toBeInTheDocument();
574
- });
575
-
576
- it('handles missing eventName prop gracefully', () => {
577
- // @ts-expect-error - Testing invalid props
578
- const { container } = render(
579
- <EventLogo
580
- eventId="event-123"
581
- organisationId="org-123"
582
- />
583
- );
584
- expect(container.firstChild).toBeInTheDocument();
585
- });
586
-
587
- it('handles missing organisationId prop gracefully', () => {
588
- // @ts-expect-error - Testing invalid props
589
- const { container } = render(
590
- <EventLogo
591
- eventId="event-123"
592
- eventName="Test Event"
593
- />
594
- );
595
- expect(container.firstChild).toBeInTheDocument();
596
- });
597
- });
598
- });
599
-
600
- describe('[component] EventLogoCompact', () => {
601
- beforeEach(async () => {
602
- vi.clearAllMocks();
603
- mockUsePublicPageContext.mockReturnValue({
604
- isPublicPage: false,
605
- supabase: { from: vi.fn() }
606
- });
607
- mockUsePublicEventLogo.mockReturnValue({
608
- logoUrl: null,
609
- fallbackText: 'TE',
610
- isLoading: false,
611
- error: null
612
- });
613
-
614
- // Set up the mocked hook
615
- const { usePublicEventLogo } = await import('../../../hooks/public/usePublicEventLogo');
616
- vi.mocked(usePublicEventLogo).mockImplementation(mockUsePublicEventLogo);
617
- });
618
-
619
- it('renders with compact size and rounded corners', () => {
620
- const { container } = render(
621
- <EventLogoCompact
622
- eventId="event-123"
623
- eventName="Test Event"
624
- organisationId="org-123"
625
- className="custom-class"
626
- />
627
- );
628
-
629
- const logo = container.firstChild as HTMLElement;
630
- expect(logo).toHaveClass('h-6', 'w-6', 'text-sm', 'rounded-sm', 'custom-class');
631
- });
632
- });
633
-
634
- describe('[component] EventLogoLarge', () => {
635
- beforeEach(async () => {
636
- vi.clearAllMocks();
637
- mockUsePublicPageContext.mockReturnValue({
638
- isPublicPage: false,
639
- supabase: { from: vi.fn() }
640
- });
641
- mockUsePublicEventLogo.mockReturnValue({
642
- logoUrl: null,
643
- fallbackText: 'TE',
644
- isLoading: false,
645
- error: null
646
- });
647
-
648
- // Set up the mocked hook
649
- const { usePublicEventLogo } = await import('../../../hooks/public/usePublicEventLogo');
650
- vi.mocked(usePublicEventLogo).mockImplementation(mockUsePublicEventLogo);
651
- });
652
-
653
- it('renders with large size and rounded corners', () => {
654
- const { container } = render(
655
- <EventLogoLarge
656
- eventId="event-123"
657
- eventName="Test Event"
658
- organisationId="org-123"
659
- className="custom-class"
660
- />
661
- );
662
-
663
- const logo = container.firstChild as HTMLElement;
664
- expect(logo).toHaveClass('h-16', 'w-16', 'text-xl', 'rounded-lg', 'custom-class');
665
- });
666
- });