@jmruthers/pace-core 0.5.75 → 0.5.76
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.
- package/dist/{DataTable-HWZQGASI.js → DataTable-4GAVPIEG.js} +48 -30
- package/dist/{PublicLoadingSpinner-BKNBT6b6.d.ts → PublicLoadingSpinner-BiNER8F5.d.ts} +28 -17
- package/dist/{chunk-33PHABLB.js → chunk-AFGTSUAD.js} +10 -127
- package/dist/chunk-AFGTSUAD.js.map +1 -0
- package/dist/{chunk-2DFZ432F.js → chunk-K34IM5CT.js} +3 -5
- package/dist/{chunk-2DFZ432F.js.map → chunk-K34IM5CT.js.map} +1 -1
- package/dist/{chunk-2CHATWBF.js → chunk-KHJS6VIA.js} +199 -35
- package/dist/chunk-KHJS6VIA.js.map +1 -0
- package/dist/{chunk-ZTT2AXMX.js → chunk-KK73ZB4E.js} +2 -2
- package/dist/{chunk-CY3AHGO4.js → chunk-M5IWZRBT.js} +1750 -2815
- package/dist/chunk-M5IWZRBT.js.map +1 -0
- package/dist/{chunk-DAXLNIDY.js → chunk-Y6TXWPJO.js} +6 -4
- package/dist/{chunk-DAXLNIDY.js.map → chunk-Y6TXWPJO.js.map} +1 -1
- package/dist/{chunk-YNUBMSMV.js → chunk-YCKPEMJA.js} +186 -263
- package/dist/chunk-YCKPEMJA.js.map +1 -0
- package/dist/components.d.ts +1 -1
- package/dist/components.js +7 -6
- package/dist/components.js.map +1 -1
- package/dist/hooks.d.ts +17 -40
- package/dist/hooks.js +6 -6
- package/dist/index.d.ts +3 -3
- package/dist/index.js +12 -10
- package/dist/index.js.map +1 -1
- package/dist/rbac/index.d.ts +54 -1
- package/dist/rbac/index.js +5 -4
- package/dist/utils.js +1 -1
- package/docs/TERMINOLOGY.md +231 -0
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContextType.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACProviderProps.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +47 -0
- package/docs/api/interfaces/UseResolvedScopeReturn.md +47 -0
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +57 -11
- package/docs/api-reference/providers.md +26 -7
- package/docs/best-practices/README.md +20 -0
- package/docs/best-practices/accessibility.md +566 -0
- package/docs/best-practices/performance-expansion.md +473 -0
- package/docs/core-concepts/authentication.md +15 -7
- package/docs/documentation-index.md +1 -1
- package/docs/documentation-templates.md +539 -0
- package/docs/getting-started/quick-start.md +16 -66
- package/docs/implementation-guides/component-styling.md +410 -0
- package/docs/implementation-guides/data-tables.md +1 -1
- package/docs/style-guide.md +39 -0
- package/package.json +1 -1
- package/src/__tests__/TEST_GUIDE_CURSOR.md +290 -0
- package/src/__tests__/helpers/supabaseMock.ts +48 -2
- package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +17 -6
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +73 -9
- package/src/components/DataTable/components/DataTableCore.tsx +280 -475
- package/src/components/DataTable/components/UnifiedTableBody.tsx +120 -153
- package/src/components/DataTable/components/index.ts +1 -2
- package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +208 -275
- package/src/components/DataTable/core/index.ts +1 -8
- package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +525 -0
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +570 -0
- package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +214 -0
- package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +224 -0
- package/src/components/DataTable/hooks/index.ts +6 -0
- package/src/components/DataTable/hooks/useColumnReordering.ts +1 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +149 -0
- package/src/components/DataTable/hooks/useDataTableState.ts +12 -6
- package/src/components/DataTable/hooks/useHierarchicalState.ts +26 -8
- package/src/components/DataTable/hooks/useTableColumns.ts +153 -0
- package/src/components/DataTable/index.ts +1 -9
- package/src/components/DataTable/utils/__tests__/COVERAGE_NOTE.md +89 -0
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +3 -6
- package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +462 -0
- package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +247 -0
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +8 -6
- package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +466 -0
- package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +265 -0
- package/src/components/DataTable/utils/errorHandling.ts +52 -460
- package/src/components/DataTable/utils/exportUtils.ts +46 -15
- package/src/components/DataTable/utils/hierarchicalSorting.ts +50 -3
- package/src/components/DataTable/utils/hierarchicalUtils.ts +167 -34
- package/src/components/DataTable/utils/index.ts +5 -0
- package/src/components/DataTable/utils/rowUtils.ts +68 -0
- package/src/components/EventSelector/EventSelector.test.tsx +672 -0
- package/src/components/Label/__tests__/Label.test.tsx +434 -0
- package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +190 -0
- package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +185 -0
- package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +313 -0
- package/src/components/Select/Select.test.tsx +143 -120
- package/src/components/Select/Select.tsx +47 -212
- package/src/components/Select/hooks.ts +36 -1
- package/src/components/Select/index.ts +2 -1
- package/src/hooks/services/__tests__/useServiceHooks.test.tsx +137 -0
- package/src/hooks/useSecureDataAccess.test.ts +32 -29
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +341 -0
- package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +437 -0
- package/src/rbac/hooks/index.ts +2 -0
- package/src/rbac/hooks/useResolvedScope.ts +232 -0
- package/src/services/__tests__/InactivityService.lifecycle.test.ts +411 -0
- package/src/services/__tests__/OrganisationService.pagination.test.ts +375 -0
- package/src/types/__tests__/README.md +114 -0
- package/src/types/__tests__/validation.test.ts +731 -0
- package/src/utils/__tests__/file-reference.test.ts +383 -0
- package/src/utils/__tests__/performanceBenchmark.test.ts +175 -0
- package/src/utils/appNameResolver.test.ts +54 -0
- package/src/validation/__tests__/csrf.unit.test.ts +63 -0
- package/src/validation/__tests__/passwordSchema.unit.test.ts +105 -0
- package/dist/chunk-2CHATWBF.js.map +0 -1
- package/dist/chunk-33PHABLB.js.map +0 -1
- package/dist/chunk-CY3AHGO4.js.map +0 -1
- package/dist/chunk-TYHR5X4W.js +0 -33
- package/dist/chunk-TYHR5X4W.js.map +0 -1
- package/dist/chunk-YNUBMSMV.js.map +0 -1
- package/dist/eventContext-BBA42P6G.js +0 -14
- package/dist/eventContext-BBA42P6G.js.map +0 -1
- package/docs/documentation-style-checklist.md +0 -294
- package/src/components/DataTable/components/DataTableBody.tsx +0 -488
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -144
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -515
- package/src/components/DataTable/core/ActionManager.ts +0 -235
- package/src/components/DataTable/core/ColumnManager.ts +0 -215
- package/src/components/DataTable/core/DataManager.ts +0 -188
- package/src/components/DataTable/core/DataTableContext.tsx +0 -181
- package/src/components/DataTable/core/LocalDataAdapter.ts +0 -264
- package/src/components/DataTable/core/PluginRegistry.ts +0 -229
- package/src/components/DataTable/core/StateManager.ts +0 -311
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -634
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -193
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -519
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -714
- package/src/components/DataTable/core/interfaces.ts +0 -338
- package/src/components/DataTable/utils/debugTools.ts +0 -583
- package/src/components/Select/Select.bug-test.tsx +0 -69
- package/src/components/Select/Select.refactored.tsx +0 -497
- /package/dist/{DataTable-HWZQGASI.js.map → DataTable-4GAVPIEG.js.map} +0 -0
- /package/dist/{chunk-ZTT2AXMX.js.map → chunk-KK73ZB4E.js.map} +0 -0
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file EventSelector Component Tests
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Components/EventSelector
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* Comprehensive test suite for the EventSelector component covering all functionality,
|
|
8
|
+
* event selection, error handling, and accessibility features.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import { screen, waitFor } from '@testing-library/react';
|
|
13
|
+
import userEvent from '@testing-library/user-event';
|
|
14
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
15
|
+
import { EventSelector, EventSelectorProps } from './EventSelector';
|
|
16
|
+
import { renderWithProviders } from '../../__tests__/helpers/test-utils';
|
|
17
|
+
import type { Event } from '../../types';
|
|
18
|
+
|
|
19
|
+
// Mock the useEvents hook
|
|
20
|
+
const mockUseEvents = vi.fn();
|
|
21
|
+
vi.mock('../../hooks/useEvents', () => ({
|
|
22
|
+
useEvents: () => mockUseEvents(),
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
// Mock child components
|
|
26
|
+
let mockOnValueChange: ((value: string) => void) | null = null;
|
|
27
|
+
|
|
28
|
+
vi.mock('../Select', () => ({
|
|
29
|
+
Select: ({ children, value, onValueChange, className }: any) => {
|
|
30
|
+
// Store the onValueChange callback for SelectItem to use
|
|
31
|
+
mockOnValueChange = onValueChange;
|
|
32
|
+
return (
|
|
33
|
+
<div data-testid="select" data-value={value} className={className}>
|
|
34
|
+
{children}
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
},
|
|
38
|
+
SelectContent: ({ children }: any) => (
|
|
39
|
+
<div data-testid="select-content">{children}</div>
|
|
40
|
+
),
|
|
41
|
+
SelectItem: ({ children, value, className }: any) => (
|
|
42
|
+
<div
|
|
43
|
+
data-testid={`select-item-${value}`}
|
|
44
|
+
className={className}
|
|
45
|
+
onClick={() => mockOnValueChange?.(value)}
|
|
46
|
+
>
|
|
47
|
+
{children}
|
|
48
|
+
</div>
|
|
49
|
+
),
|
|
50
|
+
SelectTrigger: ({ children, className }: any) => (
|
|
51
|
+
<button data-testid="select-trigger" className={className}>
|
|
52
|
+
{children}
|
|
53
|
+
</button>
|
|
54
|
+
),
|
|
55
|
+
SelectValue: ({ placeholder, children }: any) => (
|
|
56
|
+
<span data-testid="select-value">
|
|
57
|
+
{children || placeholder}
|
|
58
|
+
</span>
|
|
59
|
+
),
|
|
60
|
+
}));
|
|
61
|
+
|
|
62
|
+
vi.mock('../Alert/Alert', () => ({
|
|
63
|
+
Alert: ({ children, variant }: any) => (
|
|
64
|
+
<div data-testid="alert" data-variant={variant}>
|
|
65
|
+
{children}
|
|
66
|
+
</div>
|
|
67
|
+
),
|
|
68
|
+
AlertDescription: ({ children, className }: any) => (
|
|
69
|
+
<div data-testid="alert-description" className={className}>
|
|
70
|
+
{children}
|
|
71
|
+
</div>
|
|
72
|
+
),
|
|
73
|
+
}));
|
|
74
|
+
|
|
75
|
+
vi.mock('../Button/Button', () => ({
|
|
76
|
+
Button: ({ children, onClick, variant, size, className }: any) => (
|
|
77
|
+
<button
|
|
78
|
+
data-testid="button"
|
|
79
|
+
onClick={onClick}
|
|
80
|
+
data-variant={variant}
|
|
81
|
+
data-size={size}
|
|
82
|
+
className={className}
|
|
83
|
+
>
|
|
84
|
+
{children}
|
|
85
|
+
</button>
|
|
86
|
+
),
|
|
87
|
+
}));
|
|
88
|
+
|
|
89
|
+
vi.mock('../LoadingSpinner/LoadingSpinner', () => ({
|
|
90
|
+
LoadingSpinner: ({ size }: any) => (
|
|
91
|
+
<div data-testid="loading-spinner" data-size={size}>Loading...</div>
|
|
92
|
+
),
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
vi.mock('lucide-react', () => ({
|
|
96
|
+
RefreshCw: () => <span data-testid="icon-refresh">refresh</span>,
|
|
97
|
+
AlertCircle: () => <span data-testid="icon-alert">alert</span>,
|
|
98
|
+
Lock: () => <span data-testid="icon-lock">lock</span>,
|
|
99
|
+
Calendar: () => <span data-testid="icon-calendar">calendar</span>,
|
|
100
|
+
Star: () => <span data-testid="icon-star">star</span>,
|
|
101
|
+
}));
|
|
102
|
+
|
|
103
|
+
// Test data
|
|
104
|
+
const mockEvents: Event[] = [
|
|
105
|
+
{
|
|
106
|
+
id: 'event-1',
|
|
107
|
+
event_id: 'event-1',
|
|
108
|
+
event_name: 'Spring Festival 2024',
|
|
109
|
+
event_date: '2024-03-15T00:00:00Z',
|
|
110
|
+
event_venue: 'City Park',
|
|
111
|
+
organisation_id: 'org-1',
|
|
112
|
+
created_at: '2023-01-01T00:00:00Z',
|
|
113
|
+
updated_at: '2023-01-01T00:00:00Z',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: 'event-2',
|
|
117
|
+
event_id: 'event-2',
|
|
118
|
+
event_name: 'Summer Conference',
|
|
119
|
+
event_date: '2024-06-20T00:00:00Z',
|
|
120
|
+
event_venue: 'Convention Center',
|
|
121
|
+
organisation_id: 'org-1',
|
|
122
|
+
created_at: '2023-01-02T00:00:00Z',
|
|
123
|
+
updated_at: '2023-01-02T00:00:00Z',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'event-3',
|
|
127
|
+
event_id: 'event-3',
|
|
128
|
+
event_name: 'Winter Gala',
|
|
129
|
+
event_date: '2024-12-01T00:00:00Z',
|
|
130
|
+
event_venue: 'Grand Hotel',
|
|
131
|
+
organisation_id: 'org-1',
|
|
132
|
+
created_at: '2023-01-03T00:00:00Z',
|
|
133
|
+
updated_at: '2023-01-03T00:00:00Z',
|
|
134
|
+
},
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
const mockSelectedEvent = mockEvents[0];
|
|
138
|
+
|
|
139
|
+
const defaultMockContext = {
|
|
140
|
+
events: mockEvents,
|
|
141
|
+
selectedEvent: mockSelectedEvent,
|
|
142
|
+
isLoading: false,
|
|
143
|
+
error: null,
|
|
144
|
+
setSelectedEvent: vi.fn(),
|
|
145
|
+
refreshEvents: vi.fn().mockResolvedValue(undefined),
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
describe('EventSelector Component', () => {
|
|
149
|
+
beforeEach(() => {
|
|
150
|
+
vi.clearAllMocks();
|
|
151
|
+
|
|
152
|
+
// Setup the default mock context
|
|
153
|
+
mockUseEvents.mockReturnValue(defaultMockContext);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
afterEach(() => {
|
|
157
|
+
mockOnValueChange = null;
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('Rendering', () => {
|
|
161
|
+
it('renders with default props', () => {
|
|
162
|
+
renderWithProviders(<EventSelector />);
|
|
163
|
+
|
|
164
|
+
expect(screen.getByTestId('select')).toBeInTheDocument();
|
|
165
|
+
expect(screen.getByTestId('select-trigger')).toBeInTheDocument();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('renders with custom placeholder', () => {
|
|
169
|
+
mockUseEvents.mockReturnValue({
|
|
170
|
+
...defaultMockContext,
|
|
171
|
+
selectedEvent: null, // No selected event should show placeholder
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
renderWithProviders(<EventSelector placeholder="Choose an event" />);
|
|
175
|
+
|
|
176
|
+
expect(screen.getByTestId('select-value')).toBeInTheDocument();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('renders with custom className', () => {
|
|
180
|
+
const { container } = renderWithProviders(<EventSelector className="custom-class" />);
|
|
181
|
+
|
|
182
|
+
const select = screen.getByTestId('select');
|
|
183
|
+
expect(select).toHaveClass('custom-class');
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('renders all events in dropdown', () => {
|
|
187
|
+
renderWithProviders(<EventSelector />);
|
|
188
|
+
|
|
189
|
+
expect(screen.getByTestId('select-content')).toBeInTheDocument();
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe('Loading State', () => {
|
|
194
|
+
it('shows loading spinner when isLoading is true', () => {
|
|
195
|
+
mockUseEvents.mockReturnValue({
|
|
196
|
+
...defaultMockContext,
|
|
197
|
+
isLoading: true,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
renderWithProviders(<EventSelector />);
|
|
201
|
+
|
|
202
|
+
expect(screen.getByTestId('loading-spinner')).toBeInTheDocument();
|
|
203
|
+
expect(screen.getByText('Loading events...')).toBeInTheDocument();
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe('Error State', () => {
|
|
208
|
+
it('shows error message when error occurs', () => {
|
|
209
|
+
const error = new Error('Failed to load events');
|
|
210
|
+
mockUseEvents.mockReturnValue({
|
|
211
|
+
...defaultMockContext,
|
|
212
|
+
error,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
renderWithProviders(<EventSelector />);
|
|
216
|
+
|
|
217
|
+
expect(screen.getByTestId('alert')).toBeInTheDocument();
|
|
218
|
+
expect(screen.getByTestId('alert')).toHaveAttribute('data-variant', 'destructive');
|
|
219
|
+
expect(screen.getByText('Failed to load events')).toBeInTheDocument();
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('shows retry button when error and showRetryButton is true', () => {
|
|
223
|
+
const error = new Error('Failed to load events');
|
|
224
|
+
mockUseEvents.mockReturnValue({
|
|
225
|
+
...defaultMockContext,
|
|
226
|
+
error,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
renderWithProviders(<EventSelector showRetryButton={true} />);
|
|
230
|
+
|
|
231
|
+
expect(screen.getByTestId('button')).toBeInTheDocument();
|
|
232
|
+
expect(screen.getByText('Retry')).toBeInTheDocument();
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('hides retry button when showRetryButton is false', () => {
|
|
236
|
+
const error = new Error('Failed to load events');
|
|
237
|
+
mockUseEvents.mockReturnValue({
|
|
238
|
+
...defaultMockContext,
|
|
239
|
+
error,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
renderWithProviders(<EventSelector showRetryButton={false} />);
|
|
243
|
+
|
|
244
|
+
expect(screen.queryByTestId('button')).not.toBeInTheDocument();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('calls refreshEvents when retry button is clicked', async () => {
|
|
248
|
+
const refreshEventsMock = vi.fn().mockResolvedValue(undefined);
|
|
249
|
+
const error = new Error('Failed to load events');
|
|
250
|
+
|
|
251
|
+
mockUseEvents.mockReturnValue({
|
|
252
|
+
...defaultMockContext,
|
|
253
|
+
error,
|
|
254
|
+
refreshEvents: refreshEventsMock,
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
renderWithProviders(<EventSelector showRetryButton={true} />);
|
|
258
|
+
|
|
259
|
+
const retryButton = screen.getByTestId('button');
|
|
260
|
+
const user = userEvent.setup();
|
|
261
|
+
await user.click(retryButton);
|
|
262
|
+
|
|
263
|
+
expect(refreshEventsMock).toHaveBeenCalledTimes(1);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
describe('No Events State', () => {
|
|
268
|
+
it('shows no events message when showNoEventsMessage is true and no events', () => {
|
|
269
|
+
mockUseEvents.mockReturnValue({
|
|
270
|
+
...defaultMockContext,
|
|
271
|
+
events: [],
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
renderWithProviders(<EventSelector showNoEventsMessage={true} />);
|
|
275
|
+
|
|
276
|
+
expect(screen.getByTestId('alert')).toBeInTheDocument();
|
|
277
|
+
expect(screen.getByText('No events available.')).toBeInTheDocument();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('hides message when showNoEventsMessage is false and no events', () => {
|
|
281
|
+
mockUseEvents.mockReturnValue({
|
|
282
|
+
...defaultMockContext,
|
|
283
|
+
events: [],
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const { container } = renderWithProviders(<EventSelector showNoEventsMessage={false} />);
|
|
287
|
+
|
|
288
|
+
expect(container.firstChild).toBeNull();
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('shows refresh button when no events and showRetryButton is true', () => {
|
|
292
|
+
mockUseEvents.mockReturnValue({
|
|
293
|
+
...defaultMockContext,
|
|
294
|
+
events: [],
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
renderWithProviders(<EventSelector showRetryButton={true} />);
|
|
298
|
+
|
|
299
|
+
expect(screen.getByTestId('button')).toBeInTheDocument();
|
|
300
|
+
expect(screen.getByText('Refresh')).toBeInTheDocument();
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
describe('Event Selection', () => {
|
|
305
|
+
it('calls onEventChange when an event is selected', async () => {
|
|
306
|
+
const onEventChangeMock = vi.fn();
|
|
307
|
+
|
|
308
|
+
renderWithProviders(
|
|
309
|
+
<EventSelector onEventChange={onEventChangeMock} />
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
// Find and click an event item
|
|
313
|
+
const user = userEvent.setup();
|
|
314
|
+
const eventItem = screen.getByTestId('select-item-event-2');
|
|
315
|
+
await user.click(eventItem);
|
|
316
|
+
|
|
317
|
+
expect(onEventChangeMock).toHaveBeenCalledTimes(1);
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it('calls setSelectedEvent when an event is selected', async () => {
|
|
321
|
+
const setSelectedEventMock = vi.fn();
|
|
322
|
+
|
|
323
|
+
mockUseEvents.mockReturnValue({
|
|
324
|
+
...defaultMockContext,
|
|
325
|
+
setSelectedEvent: setSelectedEventMock,
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
renderWithProviders(<EventSelector />);
|
|
329
|
+
|
|
330
|
+
const user = userEvent.setup();
|
|
331
|
+
const eventItem = screen.getByTestId('select-item-event-2');
|
|
332
|
+
await user.click(eventItem);
|
|
333
|
+
|
|
334
|
+
expect(setSelectedEventMock).toHaveBeenCalled();
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it('displays selected event name and date', () => {
|
|
338
|
+
renderWithProviders(<EventSelector />);
|
|
339
|
+
|
|
340
|
+
expect(screen.getByTestId('select')).toHaveAttribute('data-value', 'event-1');
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
describe('Event Sorting', () => {
|
|
345
|
+
it('sorts events by date descending (newest first)', () => {
|
|
346
|
+
const unsortedEvents: Event[] = [
|
|
347
|
+
{
|
|
348
|
+
id: 'event-old',
|
|
349
|
+
event_id: 'event-old',
|
|
350
|
+
event_name: 'Old Event',
|
|
351
|
+
event_date: '2024-01-01T00:00:00Z',
|
|
352
|
+
organisation_id: 'org-1',
|
|
353
|
+
created_at: '2023-01-01T00:00:00Z',
|
|
354
|
+
updated_at: '2023-01-01T00:00:00Z',
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
id: 'event-new',
|
|
358
|
+
event_id: 'event-new',
|
|
359
|
+
event_name: 'New Event',
|
|
360
|
+
event_date: '2024-12-31T00:00:00Z',
|
|
361
|
+
organisation_id: 'org-1',
|
|
362
|
+
created_at: '2023-01-02T00:00:00Z',
|
|
363
|
+
updated_at: '2023-01-02T00:00:00Z',
|
|
364
|
+
},
|
|
365
|
+
];
|
|
366
|
+
|
|
367
|
+
mockUseEvents.mockReturnValue({
|
|
368
|
+
...defaultMockContext,
|
|
369
|
+
events: unsortedEvents,
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
renderWithProviders(<EventSelector />);
|
|
373
|
+
|
|
374
|
+
// The newest event should appear first in the DOM
|
|
375
|
+
const items = screen.getAllByTestId(/^select-item-/);
|
|
376
|
+
expect(items[0]).toHaveAttribute('data-testid', 'select-item-event-new');
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
describe('Auto-Selection', () => {
|
|
381
|
+
it('auto-selects next upcoming event when no event is selected', () => {
|
|
382
|
+
const today = new Date('2024-03-10T00:00:00Z');
|
|
383
|
+
vi.useFakeTimers({ now: today });
|
|
384
|
+
|
|
385
|
+
const setSelectedEventMock = vi.fn();
|
|
386
|
+
const onEventChangeMock = vi.fn();
|
|
387
|
+
|
|
388
|
+
mockUseEvents.mockReturnValue({
|
|
389
|
+
...defaultMockContext,
|
|
390
|
+
selectedEvent: null,
|
|
391
|
+
setSelectedEvent: setSelectedEventMock,
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
renderWithProviders(<EventSelector onEventChange={onEventChangeMock} />);
|
|
395
|
+
|
|
396
|
+
// Should auto-select the next event (event-1 with date 2024-03-15)
|
|
397
|
+
expect(setSelectedEventMock).toHaveBeenCalled();
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
describe('Event Details Display', () => {
|
|
402
|
+
it('shows event details when showEventDetails is true', () => {
|
|
403
|
+
renderWithProviders(<EventSelector showEventDetails={true} />);
|
|
404
|
+
|
|
405
|
+
expect(screen.getByTestId('select-content')).toBeInTheDocument();
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('hides event details when showEventDetails is false', () => {
|
|
409
|
+
renderWithProviders(<EventSelector showEventDetails={false} />);
|
|
410
|
+
|
|
411
|
+
// Details should not be visible in the rendered content
|
|
412
|
+
const content = screen.getByTestId('select-content');
|
|
413
|
+
expect(content).toBeInTheDocument();
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
describe('Next Event Indicator', () => {
|
|
418
|
+
it('shows next event indicator when showNextEventIndicator is true', () => {
|
|
419
|
+
const today = new Date('2024-03-10T12:00:00Z');
|
|
420
|
+
vi.useFakeTimers({ now: today });
|
|
421
|
+
|
|
422
|
+
renderWithProviders(<EventSelector showNextEventIndicator={true} />);
|
|
423
|
+
|
|
424
|
+
// Should render the star icon for next events (events-1, 2, 3 are in the future)
|
|
425
|
+
expect(screen.getAllByTestId('icon-star').length).toBeGreaterThan(0);
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it('hides next event indicator when showNextEventIndicator is false', () => {
|
|
429
|
+
renderWithProviders(<EventSelector showNextEventIndicator={false} />);
|
|
430
|
+
|
|
431
|
+
// No star icons should be present
|
|
432
|
+
expect(screen.queryByTestId('icon-star')).not.toBeInTheDocument();
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
describe('Format Event Date', () => {
|
|
437
|
+
it('formats today\'s date as "Today"', () => {
|
|
438
|
+
const today = new Date('2024-03-15T12:00:00Z');
|
|
439
|
+
vi.useFakeTimers({ now: today });
|
|
440
|
+
|
|
441
|
+
const todayEvent: Event[] = [{
|
|
442
|
+
id: 'event-today',
|
|
443
|
+
event_id: 'event-today',
|
|
444
|
+
event_name: 'Today Event',
|
|
445
|
+
event_date: '2024-03-15T00:00:00Z',
|
|
446
|
+
organisation_id: 'org-1',
|
|
447
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
448
|
+
updated_at: '2024-01-01T00:00:00Z',
|
|
449
|
+
}];
|
|
450
|
+
|
|
451
|
+
mockUseEvents.mockReturnValue({
|
|
452
|
+
...defaultMockContext,
|
|
453
|
+
events: todayEvent,
|
|
454
|
+
selectedEvent: todayEvent[0],
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
renderWithProviders(<EventSelector />);
|
|
458
|
+
|
|
459
|
+
// Should display "Today" for today's event
|
|
460
|
+
expect(screen.getByText('Today')).toBeInTheDocument();
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
it('formats tomorrow\'s date as "Tomorrow"', () => {
|
|
464
|
+
const today = new Date('2024-03-15T12:00:00Z');
|
|
465
|
+
vi.useFakeTimers({ now: today });
|
|
466
|
+
|
|
467
|
+
const tomorrowEvent: Event[] = [{
|
|
468
|
+
id: 'event-tomorrow',
|
|
469
|
+
event_id: 'event-tomorrow',
|
|
470
|
+
event_name: 'Tomorrow Event',
|
|
471
|
+
event_date: '2024-03-16T00:00:00Z',
|
|
472
|
+
organisation_id: 'org-1',
|
|
473
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
474
|
+
updated_at: '2024-01-01T00:00:00Z',
|
|
475
|
+
}];
|
|
476
|
+
|
|
477
|
+
mockUseEvents.mockReturnValue({
|
|
478
|
+
...defaultMockContext,
|
|
479
|
+
events: tomorrowEvent,
|
|
480
|
+
selectedEvent: tomorrowEvent[0],
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
renderWithProviders(<EventSelector />);
|
|
484
|
+
|
|
485
|
+
// Should display "Tomorrow" for tomorrow's event
|
|
486
|
+
expect(screen.getByText('Tomorrow')).toBeInTheDocument();
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
it('formats past/future dates as locale date string', () => {
|
|
490
|
+
const today = new Date('2024-03-15T12:00:00Z');
|
|
491
|
+
vi.useFakeTimers({ now: today });
|
|
492
|
+
|
|
493
|
+
const futureEvent: Event[] = [{
|
|
494
|
+
id: 'event-future',
|
|
495
|
+
event_id: 'event-future',
|
|
496
|
+
event_name: 'Future Event',
|
|
497
|
+
event_date: '2024-06-20T00:00:00Z',
|
|
498
|
+
organisation_id: 'org-1',
|
|
499
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
500
|
+
updated_at: '2024-01-01T00:00:00Z',
|
|
501
|
+
}];
|
|
502
|
+
|
|
503
|
+
mockUseEvents.mockReturnValue({
|
|
504
|
+
...defaultMockContext,
|
|
505
|
+
events: futureEvent,
|
|
506
|
+
selectedEvent: futureEvent[0],
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
renderWithProviders(<EventSelector />);
|
|
510
|
+
|
|
511
|
+
// Should display formatted date
|
|
512
|
+
const dateString = new Date('2024-06-20T00:00:00Z').toLocaleDateString();
|
|
513
|
+
expect(screen.getByText(dateString)).toBeInTheDocument();
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
describe('Is Next Event', () => {
|
|
518
|
+
it('identifies events on or after today as next events', () => {
|
|
519
|
+
const today = new Date('2024-03-15T12:00:00Z');
|
|
520
|
+
vi.useFakeTimers({ now: today });
|
|
521
|
+
|
|
522
|
+
const futureEvent: Event[] = [{
|
|
523
|
+
id: 'event-future',
|
|
524
|
+
event_id: 'event-future',
|
|
525
|
+
event_name: 'Future Event',
|
|
526
|
+
event_date: '2024-06-20T00:00:00Z',
|
|
527
|
+
organisation_id: 'org-1',
|
|
528
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
529
|
+
updated_at: '2024-01-01T00:00:00Z',
|
|
530
|
+
}];
|
|
531
|
+
|
|
532
|
+
mockUseEvents.mockReturnValue({
|
|
533
|
+
...defaultMockContext,
|
|
534
|
+
events: futureEvent,
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
renderWithProviders(<EventSelector showNextEventIndicator={true} />);
|
|
538
|
+
|
|
539
|
+
// Should show star indicator for future events
|
|
540
|
+
expect(screen.getByTestId('icon-star')).toBeInTheDocument();
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
it('does not identify past events as next events', () => {
|
|
544
|
+
const today = new Date('2024-03-15T12:00:00Z');
|
|
545
|
+
vi.useFakeTimers({ now: today });
|
|
546
|
+
|
|
547
|
+
const pastEvent: Event[] = [{
|
|
548
|
+
id: 'event-past',
|
|
549
|
+
event_id: 'event-past',
|
|
550
|
+
event_name: 'Past Event',
|
|
551
|
+
event_date: '2024-01-01T00:00:00Z',
|
|
552
|
+
organisation_id: 'org-1',
|
|
553
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
554
|
+
updated_at: '2024-01-01T00:00:00Z',
|
|
555
|
+
}];
|
|
556
|
+
|
|
557
|
+
mockUseEvents.mockReturnValue({
|
|
558
|
+
...defaultMockContext,
|
|
559
|
+
events: pastEvent,
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
renderWithProviders(<EventSelector showNextEventIndicator={true} />);
|
|
563
|
+
|
|
564
|
+
// Should not show star indicator for past events
|
|
565
|
+
expect(screen.queryByTestId('icon-star')).not.toBeInTheDocument();
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
describe('Integration with useEvents Hook', () => {
|
|
570
|
+
it('uses events from useEvents hook', () => {
|
|
571
|
+
const customEvents: Event[] = [
|
|
572
|
+
{
|
|
573
|
+
id: 'custom-event',
|
|
574
|
+
event_id: 'custom-event',
|
|
575
|
+
event_name: 'Custom Event',
|
|
576
|
+
event_date: '2024-12-01T00:00:00Z',
|
|
577
|
+
organisation_id: 'org-1',
|
|
578
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
579
|
+
updated_at: '2024-01-01T00:00:00Z',
|
|
580
|
+
},
|
|
581
|
+
];
|
|
582
|
+
|
|
583
|
+
mockUseEvents.mockReturnValue({
|
|
584
|
+
...defaultMockContext,
|
|
585
|
+
events: customEvents,
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
renderWithProviders(<EventSelector />);
|
|
589
|
+
|
|
590
|
+
expect(mockUseEvents).toHaveBeenCalled();
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
it('calls setSelectedEvent from useEvents hook when event changes', async () => {
|
|
594
|
+
const setSelectedEventMock = vi.fn();
|
|
595
|
+
|
|
596
|
+
mockUseEvents.mockReturnValue({
|
|
597
|
+
...defaultMockContext,
|
|
598
|
+
setSelectedEvent: setSelectedEventMock,
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
renderWithProviders(<EventSelector />);
|
|
602
|
+
|
|
603
|
+
const user = userEvent.setup();
|
|
604
|
+
const eventItem = screen.getByTestId('select-item-event-2');
|
|
605
|
+
await user.click(eventItem);
|
|
606
|
+
|
|
607
|
+
expect(setSelectedEventMock).toHaveBeenCalled();
|
|
608
|
+
});
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
describe('Edge Cases', () => {
|
|
612
|
+
it('handles events without event_date gracefully', () => {
|
|
613
|
+
const eventsWithoutDate: Event[] = [{
|
|
614
|
+
id: 'no-date-event',
|
|
615
|
+
event_id: 'no-date-event',
|
|
616
|
+
event_name: 'Event Without Date',
|
|
617
|
+
organisation_id: 'org-1',
|
|
618
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
619
|
+
updated_at: '2024-01-01T00:00:00Z',
|
|
620
|
+
}];
|
|
621
|
+
|
|
622
|
+
mockUseEvents.mockReturnValue({
|
|
623
|
+
...defaultMockContext,
|
|
624
|
+
events: eventsWithoutDate,
|
|
625
|
+
selectedEvent: eventsWithoutDate[0],
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
renderWithProviders(<EventSelector />);
|
|
629
|
+
|
|
630
|
+
expect(screen.getByTestId('select')).toBeInTheDocument();
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
it('handles events with missing venue gracefully', () => {
|
|
634
|
+
const eventsWithoutVenue: Event[] = [{
|
|
635
|
+
id: 'no-venue-event',
|
|
636
|
+
event_id: 'no-venue-event',
|
|
637
|
+
event_name: 'Event Without Venue',
|
|
638
|
+
event_date: '2024-12-01T00:00:00Z',
|
|
639
|
+
organisation_id: 'org-1',
|
|
640
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
641
|
+
updated_at: '2024-01-01T00:00:00Z',
|
|
642
|
+
}];
|
|
643
|
+
|
|
644
|
+
mockUseEvents.mockReturnValue({
|
|
645
|
+
...defaultMockContext,
|
|
646
|
+
events: eventsWithoutVenue,
|
|
647
|
+
selectedEvent: eventsWithoutVenue[0],
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
renderWithProviders(<EventSelector />);
|
|
651
|
+
|
|
652
|
+
expect(screen.getByTestId('select')).toBeInTheDocument();
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
it('handles rapid event changes without errors', async () => {
|
|
656
|
+
const user = userEvent.setup();
|
|
657
|
+
|
|
658
|
+
renderWithProviders(<EventSelector />);
|
|
659
|
+
|
|
660
|
+
// Rapidly change events
|
|
661
|
+
const event1 = screen.getByTestId('select-item-event-1');
|
|
662
|
+
const event2 = screen.getByTestId('select-item-event-2');
|
|
663
|
+
|
|
664
|
+
await user.click(event1);
|
|
665
|
+
await user.click(event2);
|
|
666
|
+
await user.click(event1);
|
|
667
|
+
|
|
668
|
+
expect(screen.getByTestId('select')).toBeInTheDocument();
|
|
669
|
+
});
|
|
670
|
+
});
|
|
671
|
+
});
|
|
672
|
+
|