@jmruthers/pace-core 0.2.5 → 0.2.7
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-BHlzyKZP.d.ts → DataTable-C1AEm9Cx.d.ts} +1 -1
- package/dist/{DataTable-GEY5U7OI.js → DataTable-EEUDXPE5.js} +2 -8
- package/dist/{api-T6CBS7IO.js → api-ETQ6YJ3C.js} +2 -3
- package/dist/{chunk-DY5E3AT7.js → chunk-BEZRLNK3.js} +13 -3
- package/dist/chunk-BEZRLNK3.js.map +1 -0
- package/dist/{chunk-ANE4PDC2.js → chunk-C5G2A4PO.js} +159 -6
- package/dist/chunk-C5G2A4PO.js.map +1 -0
- package/dist/{chunk-WYB6MBZA.js → chunk-EWKPTNPO.js} +579 -973
- package/dist/chunk-EWKPTNPO.js.map +1 -0
- package/dist/{chunk-TMRLB2LA.js → chunk-HEMJ4SUJ.js} +2 -2
- package/dist/{chunk-O4T53L7X.js → chunk-HNDFPXUU.js} +5 -5
- package/dist/{chunk-UY7AM4QG.js → chunk-RRUYHORU.js} +161 -74
- package/dist/chunk-RRUYHORU.js.map +1 -0
- package/dist/{chunk-PFRRIDYA.js → chunk-TIVL4UQ7.js} +2 -2
- package/dist/{chunk-2MKP6IYD.js → chunk-VYG4AXYW.js} +2 -2
- package/dist/components.d.ts +2 -2
- package/dist/components.js +15 -16
- package/dist/components.js.map +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +16 -17
- package/dist/index.js.map +1 -1
- package/dist/providers.js +2 -2
- package/dist/rbac/index.js +25 -20
- package/dist/rbac/index.js.map +1 -1
- package/dist/styles/core.css +83 -62
- package/dist/{types-CInEi-ng.d.ts → types-DiRQsGJs.d.ts} +0 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.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/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +33 -33
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EventContextType.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/EventProviderProps.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.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/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.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/PaletteData.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/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/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/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 +10 -10
- package/docs/architecture/README.md +1 -1
- package/package.json +1 -1
- package/src/__tests__/shared/testUtils.optimized.tsx +65 -7
- package/src/components/DataTable/DataTable.tsx +1 -3
- package/src/components/DataTable/__tests__/DataTable.errorHandling.test.tsx +0 -8
- package/src/components/DataTable/__tests__/DataTable.hierarchical.test.tsx +17 -12
- package/src/components/DataTable/__tests__/DataTable.infinite-loop.test.tsx +0 -1
- package/src/components/DataTable/__tests__/DataTable.integration.test.tsx +4 -12
- package/src/components/DataTable/__tests__/DataTable.performance.test.tsx +0 -8
- package/src/components/DataTable/__tests__/DataTable.permissions.test.tsx +21 -11
- package/src/components/DataTable/__tests__/DataTable.sorting.test.tsx +321 -0
- package/src/components/DataTable/__tests__/DataTable.userWorkflows.test.tsx +21 -11
- package/src/components/DataTable/__tests__/DataTable.workflowValidation.test.tsx +94 -0
- package/src/components/DataTable/__tests__/DataTable.workflows.test.tsx +25 -15
- package/src/components/DataTable/__tests__/README.md +11 -2
- package/src/components/DataTable/__tests__/performance-regression.test.tsx +0 -11
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +0 -1
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +2 -2
- package/src/components/DataTable/components/DataTableBody.tsx +34 -35
- package/src/components/DataTable/components/DataTableCore.tsx +205 -133
- package/src/components/DataTable/components/DataTableToolbar.tsx +9 -10
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -7
- package/src/components/DataTable/components/EditableRow.tsx +6 -7
- package/src/components/DataTable/components/FilterRow.tsx +0 -1
- package/src/components/DataTable/components/GroupingDropdown.tsx +2 -2
- package/src/components/DataTable/components/UnifiedTableBody.tsx +83 -281
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +9 -89
- package/src/components/DataTable/components/__tests__/DataTable.accessibility.test.tsx +111 -5
- package/src/components/DataTable/components/__tests__/DataTable.integration.test.tsx +82 -13
- package/src/components/DataTable/components/__tests__/DataTable.performance.test.tsx +0 -1
- package/src/components/DataTable/components/__tests__/DataTable.real.test.tsx +2 -2
- package/src/components/DataTable/components/__tests__/DataTable.security.test.tsx +0 -1
- package/src/components/DataTable/components/__tests__/DataTable.unit.test.tsx +2 -2
- package/src/components/DataTable/components/__tests__/FilteringToggle.unit.test.tsx +3 -0
- package/src/components/DataTable/components/index.ts +0 -1
- package/src/components/DataTable/core/DataTableContext.tsx +0 -1
- package/src/components/DataTable/index.ts +0 -2
- package/src/components/DataTable/types.ts +0 -2
- package/src/components/Input/Input.tsx +2 -2
- package/src/components/Input/__tests__/Input.unit.test.tsx +4 -4
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -2
- package/src/components/RBAC/PagePermissionGuard.tsx +13 -0
- package/src/components/RBAC/__tests__/PagePermissionGuard.unit.test.tsx +10 -1
- package/src/components/Select/Select.tsx +7 -1
- package/src/components/__tests__/EdgeCaseTesting.enhanced.test.tsx +2 -1
- package/src/hooks/__tests__/useRBAC.unit.test.ts +32 -24
- package/src/providers/RBACProvider.tsx +14 -2
- package/src/providers/__tests__/UnifiedAuthProvider.unit.test.tsx +11 -3
- package/src/rbac/__tests__/cache-invalidation.test.ts +2 -2
- package/src/rbac/__tests__/cache.test.ts +3 -3
- package/src/rbac/hooks.ts +15 -7
- package/src/styles/core.css +83 -62
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +13 -18
- package/src/utils/storage/__tests__/helpers.unit.test.ts +9 -7
- package/dist/cache-I72HKDOA.js +0 -12
- package/dist/cache-I72HKDOA.js.map +0 -1
- package/dist/chunk-ANE4PDC2.js.map +0 -1
- package/dist/chunk-DY5E3AT7.js.map +0 -1
- package/dist/chunk-MRRFJ6SA.js +0 -161
- package/dist/chunk-MRRFJ6SA.js.map +0 -1
- package/dist/chunk-UY7AM4QG.js.map +0 -1
- package/dist/chunk-WYB6MBZA.js.map +0 -1
- package/src/components/DataTable/__tests__/DataTable.autoSizing.test.tsx +0 -526
- package/src/components/DataTable/components/DataTableHeader.tsx +0 -31
- package/src/components/DataTable/components/__tests__/DataTableHeader.unit.test.tsx +0 -143
- package/src/components/DataTable/examples/AutoSizingExample.tsx +0 -180
- package/src/components/DataTable/examples/ColumnSizingComparison.tsx +0 -235
- package/src/components/DataTable/utils/__tests__/columnSizing.test.ts +0 -237
- package/src/components/DataTable/utils/columnSizing.ts +0 -125
- /package/dist/{DataTable-GEY5U7OI.js.map → DataTable-EEUDXPE5.js.map} +0 -0
- /package/dist/{api-T6CBS7IO.js.map → api-ETQ6YJ3C.js.map} +0 -0
- /package/dist/{chunk-TMRLB2LA.js.map → chunk-HEMJ4SUJ.js.map} +0 -0
- /package/dist/{chunk-O4T53L7X.js.map → chunk-HNDFPXUU.js.map} +0 -0
- /package/dist/{chunk-PFRRIDYA.js.map → chunk-TIVL4UQ7.js.map} +0 -0
- /package/dist/{chunk-2MKP6IYD.js.map → chunk-VYG4AXYW.js.map} +0 -0
|
@@ -1,526 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file DataTable Auto-Sizing Tests
|
|
3
|
-
* @package @jmruthers/pace-core
|
|
4
|
-
* @module Components/DataTable/__tests__
|
|
5
|
-
* @since 0.4.33
|
|
6
|
-
*
|
|
7
|
-
* Tests for automatic column width adjustment based on content.
|
|
8
|
-
*/
|
|
9
|
-
import { userEvent } from '@testing-library/user-event';
|
|
10
|
-
|
|
11
|
-
import React from 'react';
|
|
12
|
-
import { screen, waitFor } from '@testing-library/react';
|
|
13
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
14
|
-
import '@testing-library/jest-dom';
|
|
15
|
-
|
|
16
|
-
import { DataTable } from '../DataTable';
|
|
17
|
-
import type { DataTableFeatureConfig } from '../types';
|
|
18
|
-
import { errorTestingUtils, TestErrorBoundary } from '../../__tests__/ErrorTesting.enhanced.test';
|
|
19
|
-
import { renderWithProviders, testDataGenerators } from '../../../__tests__/shared';
|
|
20
|
-
|
|
21
|
-
// Mock lucide-react icons
|
|
22
|
-
vi.mock('lucide-react', () => {
|
|
23
|
-
const React = require('react');
|
|
24
|
-
const createIcon = (name: string) =>
|
|
25
|
-
React.forwardRef((props: any, ref: any) =>
|
|
26
|
-
React.createElement('svg', {
|
|
27
|
-
ref,
|
|
28
|
-
...props,
|
|
29
|
-
'data-testid': `lucide-${name.toLowerCase()}`,
|
|
30
|
-
width: '24',
|
|
31
|
-
height: '24',
|
|
32
|
-
viewBox: '0 0 24 24',
|
|
33
|
-
fill: 'none',
|
|
34
|
-
stroke: 'currentColor',
|
|
35
|
-
strokeWidth: '2',
|
|
36
|
-
strokeLinecap: 'round',
|
|
37
|
-
strokeLinejoin: 'round',
|
|
38
|
-
})
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
return {
|
|
42
|
-
ChevronDown: createIcon('ChevronDown'),
|
|
43
|
-
ChevronUp: createIcon('ChevronUp'),
|
|
44
|
-
ChevronLeft: createIcon('ChevronLeft'),
|
|
45
|
-
ChevronRight: createIcon('ChevronRight'),
|
|
46
|
-
ChevronsLeft: createIcon('ChevronsLeft'),
|
|
47
|
-
ChevronsRight: createIcon('ChevronsRight'),
|
|
48
|
-
ChevronsUp: createIcon('ChevronsUp'),
|
|
49
|
-
ChevronsDown: createIcon('ChevronsDown'),
|
|
50
|
-
ChevronsUpDown: createIcon('ChevronsUpDown'),
|
|
51
|
-
Search: createIcon('Search'),
|
|
52
|
-
X: createIcon('X'),
|
|
53
|
-
Check: createIcon('Check'),
|
|
54
|
-
Plus: createIcon('Plus'),
|
|
55
|
-
Minus: createIcon('Minus'),
|
|
56
|
-
Edit: createIcon('Edit'),
|
|
57
|
-
Pencil: createIcon('Pencil'),
|
|
58
|
-
Trash: createIcon('Trash'),
|
|
59
|
-
Trash2: createIcon('Trash2'),
|
|
60
|
-
Eye: createIcon('Eye'),
|
|
61
|
-
EyeOff: createIcon('EyeOff'),
|
|
62
|
-
Lock: createIcon('Lock'),
|
|
63
|
-
Unlock: createIcon('Unlock'),
|
|
64
|
-
User: createIcon('User'),
|
|
65
|
-
Users: createIcon('Users'),
|
|
66
|
-
Settings: createIcon('Settings'),
|
|
67
|
-
Settings2: createIcon('Settings2'),
|
|
68
|
-
Home: createIcon('Home'),
|
|
69
|
-
Menu: createIcon('Menu'),
|
|
70
|
-
MoreHorizontal: createIcon('MoreHorizontal'),
|
|
71
|
-
MoreVertical: createIcon('MoreVertical'),
|
|
72
|
-
Filter: createIcon('Filter'),
|
|
73
|
-
Download: createIcon('Download'),
|
|
74
|
-
Upload: createIcon('Upload'),
|
|
75
|
-
RefreshCw: createIcon('RefreshCw'),
|
|
76
|
-
AlertCircle: createIcon('AlertCircle'),
|
|
77
|
-
CheckCircle: createIcon('CheckCircle'),
|
|
78
|
-
Info: createIcon('Info'),
|
|
79
|
-
Warning: createIcon('Warning'),
|
|
80
|
-
FileText: createIcon('FileText'),
|
|
81
|
-
KeyRound: createIcon('KeyRound'),
|
|
82
|
-
LogOut: createIcon('LogOut'),
|
|
83
|
-
ArrowUpDown: createIcon('ArrowUpDown'),
|
|
84
|
-
ArrowUp: createIcon('ArrowUp'),
|
|
85
|
-
ArrowDown: createIcon('ArrowDown'),
|
|
86
|
-
RotateCcw: createIcon('RotateCcw'),
|
|
87
|
-
RotateCw: createIcon('RotateCw'),
|
|
88
|
-
Copy: createIcon('Copy'),
|
|
89
|
-
ExternalLink: createIcon('ExternalLink'),
|
|
90
|
-
Calendar: createIcon('Calendar'),
|
|
91
|
-
Clock: createIcon('Clock'),
|
|
92
|
-
Database: createIcon('Database'),
|
|
93
|
-
File: createIcon('File'),
|
|
94
|
-
Folder: createIcon('Folder'),
|
|
95
|
-
Globe: createIcon('Globe'),
|
|
96
|
-
HardDrive: createIcon('HardDrive'),
|
|
97
|
-
HelpCircle: createIcon('HelpCircle'),
|
|
98
|
-
Image: createIcon('Image'),
|
|
99
|
-
Link: createIcon('Link'),
|
|
100
|
-
Mail: createIcon('Mail'),
|
|
101
|
-
MapPin: createIcon('MapPin'),
|
|
102
|
-
Phone: createIcon('Phone'),
|
|
103
|
-
PieChart: createIcon('PieChart'),
|
|
104
|
-
Play: createIcon('Play'),
|
|
105
|
-
Save: createIcon('Save'),
|
|
106
|
-
Share: createIcon('Share'),
|
|
107
|
-
Star: createIcon('Star'),
|
|
108
|
-
Tag: createIcon('Tag'),
|
|
109
|
-
Target: createIcon('Target'),
|
|
110
|
-
TrendingUp: createIcon('TrendingUp'),
|
|
111
|
-
Volume2: createIcon('Volume2'),
|
|
112
|
-
Wifi: createIcon('Wifi'),
|
|
113
|
-
Zap: createIcon('Zap'),
|
|
114
|
-
};
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
// Mock performance APIs
|
|
118
|
-
vi.mock('../../hooks/useDataTablePerformance', () => ({
|
|
119
|
-
useDataTablePerformance: () => ({
|
|
120
|
-
startRender: vi.fn(),
|
|
121
|
-
endRender: vi.fn(),
|
|
122
|
-
getMetrics: () => ({
|
|
123
|
-
renderTime: 16.5,
|
|
124
|
-
memoryUsage: 45.2,
|
|
125
|
-
visibleRows: 10,
|
|
126
|
-
totalRows: 100,
|
|
127
|
-
paginationMode: 'client',
|
|
128
|
-
}),
|
|
129
|
-
}),
|
|
130
|
-
}));
|
|
131
|
-
|
|
132
|
-
interface TestData {
|
|
133
|
-
id: string;
|
|
134
|
-
shortText: string;
|
|
135
|
-
longText: string;
|
|
136
|
-
mediumText: string;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const testData: TestData[] = [
|
|
140
|
-
{
|
|
141
|
-
id: '1',
|
|
142
|
-
shortText: 'A',
|
|
143
|
-
longText: 'This is a very long text that should make the column wider',
|
|
144
|
-
mediumText: 'Medium length text'
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
id: '2',
|
|
148
|
-
shortText: 'B',
|
|
149
|
-
longText: 'Another very long text that should also make the column wider',
|
|
150
|
-
mediumText: 'Another medium text'
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
id: '3',
|
|
154
|
-
shortText: 'C',
|
|
155
|
-
longText: 'Yet another extremely long text that should definitely make this column the widest',
|
|
156
|
-
mediumText: 'Yet another medium'
|
|
157
|
-
}
|
|
158
|
-
];
|
|
159
|
-
|
|
160
|
-
const testColumns = [
|
|
161
|
-
{
|
|
162
|
-
id: 'shortText',
|
|
163
|
-
accessorKey: 'shortText',
|
|
164
|
-
header: 'Short',
|
|
165
|
-
enableSorting: true,
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
id: 'mediumText',
|
|
169
|
-
accessorKey: 'mediumText',
|
|
170
|
-
header: 'Medium',
|
|
171
|
-
enableSorting: true,
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
id: 'longText',
|
|
175
|
-
accessorKey: 'longText',
|
|
176
|
-
header: 'Long Text Column',
|
|
177
|
-
enableSorting: true,
|
|
178
|
-
},
|
|
179
|
-
];
|
|
180
|
-
|
|
181
|
-
const featuresWithAutoSizing: DataTableFeatureConfig = {
|
|
182
|
-
search: false,
|
|
183
|
-
pagination: false,
|
|
184
|
-
sorting: true,
|
|
185
|
-
filtering: false,
|
|
186
|
-
import: false,
|
|
187
|
-
export: false,
|
|
188
|
-
selection: false,
|
|
189
|
-
creation: false,
|
|
190
|
-
editing: false,
|
|
191
|
-
deletion: false,
|
|
192
|
-
deleteSelected: false,
|
|
193
|
-
grouping: false,
|
|
194
|
-
columnVisibility: false,
|
|
195
|
-
columnReordering: false,
|
|
196
|
-
autoColumnSizing: true,
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
const featuresWithoutAutoSizing: DataTableFeatureConfig = {
|
|
200
|
-
search: false,
|
|
201
|
-
pagination: false,
|
|
202
|
-
sorting: true,
|
|
203
|
-
filtering: false,
|
|
204
|
-
import: false,
|
|
205
|
-
export: false,
|
|
206
|
-
selection: false,
|
|
207
|
-
creation: false,
|
|
208
|
-
editing: false,
|
|
209
|
-
deletion: false,
|
|
210
|
-
deleteSelected: false,
|
|
211
|
-
grouping: false,
|
|
212
|
-
columnVisibility: false,
|
|
213
|
-
columnReordering: false,
|
|
214
|
-
autoColumnSizing: false,
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
describe('DataTable Auto-Sizing', () => {
|
|
218
|
-
beforeEach(() => {
|
|
219
|
-
vi.clearAllMocks();
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('renders table with auto-sizing enabled', () => {
|
|
223
|
-
renderWithProviders(
|
|
224
|
-
<DataTable
|
|
225
|
-
data={testData}
|
|
226
|
-
columns={testColumns}
|
|
227
|
-
features={featuresWithAutoSizing}
|
|
228
|
-
title="Auto-Sizing Table"
|
|
229
|
-
/>
|
|
230
|
-
);
|
|
231
|
-
|
|
232
|
-
const table = screen.getByRole('table');
|
|
233
|
-
expect(table).toBeInTheDocument();
|
|
234
|
-
|
|
235
|
-
// Check that table has auto layout
|
|
236
|
-
expect(table).toHaveStyle({ tableLayout: 'auto' });
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
it('renders table with fixed layout when auto-sizing disabled', () => {
|
|
240
|
-
renderWithProviders(
|
|
241
|
-
<DataTable
|
|
242
|
-
data={testData}
|
|
243
|
-
columns={testColumns}
|
|
244
|
-
features={featuresWithoutAutoSizing}
|
|
245
|
-
title="Fixed Layout Table"
|
|
246
|
-
/>
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
const table = screen.getByRole('table');
|
|
250
|
-
expect(table).toBeInTheDocument();
|
|
251
|
-
|
|
252
|
-
// Check that table has fixed layout
|
|
253
|
-
expect(table).toHaveStyle({ tableLayout: 'fixed' });
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it('applies column sizing configuration when auto-sizing enabled', () => {
|
|
257
|
-
renderWithProviders(
|
|
258
|
-
<DataTable
|
|
259
|
-
data={testData}
|
|
260
|
-
columns={testColumns}
|
|
261
|
-
features={featuresWithAutoSizing}
|
|
262
|
-
title="Auto-Sizing Table"
|
|
263
|
-
/>
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
// The table should render without errors
|
|
267
|
-
expect(screen.getByRole('table')).toBeInTheDocument();
|
|
268
|
-
|
|
269
|
-
// Check that all columns are rendered
|
|
270
|
-
expect(screen.getByText('Short')).toBeInTheDocument();
|
|
271
|
-
expect(screen.getByText('Medium')).toBeInTheDocument();
|
|
272
|
-
expect(screen.getByText('Long Text Column')).toBeInTheDocument();
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
it('handles empty data with auto-sizing', () => {
|
|
276
|
-
renderWithProviders(
|
|
277
|
-
<DataTable
|
|
278
|
-
data={[]}
|
|
279
|
-
columns={testColumns}
|
|
280
|
-
features={featuresWithAutoSizing}
|
|
281
|
-
title="Empty Auto-Sizing Table"
|
|
282
|
-
/>
|
|
283
|
-
);
|
|
284
|
-
|
|
285
|
-
const table = screen.getByRole('table');
|
|
286
|
-
expect(table).toBeInTheDocument();
|
|
287
|
-
expect(table).toHaveStyle({ tableLayout: 'auto' });
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
it('handles single row data with auto-sizing', () => {
|
|
291
|
-
renderWithProviders(
|
|
292
|
-
<DataTable
|
|
293
|
-
data={[testData[0]]}
|
|
294
|
-
columns={testColumns}
|
|
295
|
-
features={featuresWithAutoSizing}
|
|
296
|
-
title="Single Row Auto-Sizing Table"
|
|
297
|
-
/>
|
|
298
|
-
);
|
|
299
|
-
|
|
300
|
-
const table = screen.getByRole('table');
|
|
301
|
-
expect(table).toBeInTheDocument();
|
|
302
|
-
expect(table).toHaveStyle({ tableLayout: 'auto' });
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
it('handles columns with undefined/null values in auto-sizing', () => {
|
|
306
|
-
const dataWithNulls: TestData[] = [
|
|
307
|
-
{
|
|
308
|
-
id: '1',
|
|
309
|
-
shortText: 'A',
|
|
310
|
-
longText: 'This is a very long text',
|
|
311
|
-
mediumText: 'Medium text'
|
|
312
|
-
},
|
|
313
|
-
{
|
|
314
|
-
id: '2',
|
|
315
|
-
shortText: '',
|
|
316
|
-
longText: null as any,
|
|
317
|
-
mediumText: undefined as any
|
|
318
|
-
}
|
|
319
|
-
];
|
|
320
|
-
|
|
321
|
-
renderWithProviders(
|
|
322
|
-
<DataTable
|
|
323
|
-
data={dataWithNulls}
|
|
324
|
-
columns={testColumns}
|
|
325
|
-
features={featuresWithAutoSizing}
|
|
326
|
-
title="Null Values Auto-Sizing Table"
|
|
327
|
-
/>
|
|
328
|
-
);
|
|
329
|
-
|
|
330
|
-
const table = screen.getByRole('table');
|
|
331
|
-
expect(table).toBeInTheDocument();
|
|
332
|
-
expect(table).toHaveStyle({ tableLayout: 'auto' });
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
it('maintains functionality with auto-sizing enabled', () => {
|
|
336
|
-
renderWithProviders(
|
|
337
|
-
<DataTable
|
|
338
|
-
data={testData}
|
|
339
|
-
columns={testColumns}
|
|
340
|
-
features={featuresWithAutoSizing}
|
|
341
|
-
title="Functional Auto-Sizing Table"
|
|
342
|
-
/>
|
|
343
|
-
);
|
|
344
|
-
|
|
345
|
-
// Check that sorting still works
|
|
346
|
-
const shortHeader = screen.getByText('Short');
|
|
347
|
-
expect(shortHeader).toBeInTheDocument();
|
|
348
|
-
|
|
349
|
-
// Check that data is displayed
|
|
350
|
-
expect(screen.getByText('A')).toBeInTheDocument();
|
|
351
|
-
expect(screen.getByText('This is a very long text that should make the column wider')).toBeInTheDocument();
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
it('handles large datasets with auto-sizing (performance test)', () => {
|
|
355
|
-
const largeData = Array.from({ length: 1000 }, (_, i) => ({
|
|
356
|
-
id: i.toString(),
|
|
357
|
-
shortText: `A${i}`,
|
|
358
|
-
longText: `This is a very long text for row ${i} that should make the column wider`,
|
|
359
|
-
mediumText: `Medium text ${i}`
|
|
360
|
-
}));
|
|
361
|
-
|
|
362
|
-
renderWithProviders(
|
|
363
|
-
<DataTable
|
|
364
|
-
data={largeData}
|
|
365
|
-
columns={testColumns}
|
|
366
|
-
features={featuresWithAutoSizing}
|
|
367
|
-
title="Large Dataset Auto-Sizing Table"
|
|
368
|
-
/>
|
|
369
|
-
);
|
|
370
|
-
|
|
371
|
-
const table = screen.getByRole('table');
|
|
372
|
-
expect(table).toBeInTheDocument();
|
|
373
|
-
expect(table).toHaveStyle({ tableLayout: 'auto' });
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
it('applies min-width constraints in auto-sizing', () => {
|
|
377
|
-
renderWithProviders(
|
|
378
|
-
<DataTable
|
|
379
|
-
data={testData}
|
|
380
|
-
columns={testColumns}
|
|
381
|
-
features={featuresWithAutoSizing}
|
|
382
|
-
title="Min-Width Auto-Sizing Table"
|
|
383
|
-
/>
|
|
384
|
-
);
|
|
385
|
-
|
|
386
|
-
const table = screen.getByRole('table');
|
|
387
|
-
expect(table).toBeInTheDocument();
|
|
388
|
-
|
|
389
|
-
// The auto-sizing should still work with min-width constraints
|
|
390
|
-
expect(table).toHaveStyle({ tableLayout: 'auto' });
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
it('handles column reordering with auto-sizing', () => {
|
|
394
|
-
const featuresWithReordering: DataTableFeatureConfig = {
|
|
395
|
-
...featuresWithAutoSizing,
|
|
396
|
-
columnReordering: true,
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
renderWithProviders(
|
|
400
|
-
<DataTable
|
|
401
|
-
data={testData}
|
|
402
|
-
columns={testColumns}
|
|
403
|
-
features={featuresWithReordering}
|
|
404
|
-
title="Reordering Auto-Sizing Table"
|
|
405
|
-
/>
|
|
406
|
-
);
|
|
407
|
-
|
|
408
|
-
const table = screen.getByRole('table');
|
|
409
|
-
expect(table).toBeInTheDocument();
|
|
410
|
-
expect(table).toHaveStyle({ tableLayout: 'auto' });
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
it('handles column visibility with auto-sizing', () => {
|
|
414
|
-
const featuresWithVisibility: DataTableFeatureConfig = {
|
|
415
|
-
...featuresWithAutoSizing,
|
|
416
|
-
columnVisibility: true,
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
renderWithProviders(
|
|
420
|
-
<DataTable
|
|
421
|
-
data={testData}
|
|
422
|
-
columns={testColumns}
|
|
423
|
-
features={featuresWithVisibility}
|
|
424
|
-
title="Visibility Auto-Sizing Table"
|
|
425
|
-
/>
|
|
426
|
-
);
|
|
427
|
-
|
|
428
|
-
const table = screen.getByRole('table');
|
|
429
|
-
expect(table).toBeInTheDocument();
|
|
430
|
-
expect(table).toHaveStyle({ tableLayout: 'auto' });
|
|
431
|
-
});
|
|
432
|
-
describe('DataTable Error Handling', () => {
|
|
433
|
-
const user = userEvent.setup();
|
|
434
|
-
let restoreConsole: (() => void) | null = null;
|
|
435
|
-
|
|
436
|
-
beforeEach(() => {
|
|
437
|
-
restoreConsole = errorTestingUtils.suppressConsoleErrors();
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
afterEach(() => {
|
|
441
|
-
if (restoreConsole) {
|
|
442
|
-
restoreConsole();
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
it('should handle component errors gracefully', () => {
|
|
447
|
-
const ErrorComponent = () => {
|
|
448
|
-
throw new Error('DataTable component error');
|
|
449
|
-
};
|
|
450
|
-
|
|
451
|
-
renderWithProviders(
|
|
452
|
-
<TestErrorBoundary>
|
|
453
|
-
<ErrorComponent />
|
|
454
|
-
</TestErrorBoundary>
|
|
455
|
-
);
|
|
456
|
-
|
|
457
|
-
expect(screen.getByTestId('error-boundary')).toBeInTheDocument();
|
|
458
|
-
expect(screen.getByText('Error: DataTable component error')).toBeInTheDocument();
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
it('should handle async errors', async () => {
|
|
462
|
-
const AsyncErrorComponent = ({ shouldFail }: { shouldFail: boolean }) => {
|
|
463
|
-
const [error, setError] = React.useState<Error | null>(null);
|
|
464
|
-
|
|
465
|
-
React.useEffect(() => {
|
|
466
|
-
if (shouldFail) {
|
|
467
|
-
setError(new Error('Async error'));
|
|
468
|
-
}
|
|
469
|
-
}, [shouldFail]);
|
|
470
|
-
|
|
471
|
-
if (error) {
|
|
472
|
-
throw error;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
return <div>Async component</div>;
|
|
476
|
-
};
|
|
477
|
-
|
|
478
|
-
renderWithProviders(
|
|
479
|
-
<TestErrorBoundary>
|
|
480
|
-
<AsyncErrorComponent shouldFail={true} />
|
|
481
|
-
</TestErrorBoundary>
|
|
482
|
-
);
|
|
483
|
-
|
|
484
|
-
await waitFor(() => {
|
|
485
|
-
expect(screen.getByTestId('error-boundary')).toBeInTheDocument();
|
|
486
|
-
});
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
it('should handle user interaction errors', async () => {
|
|
490
|
-
const user = userEvent.setup();
|
|
491
|
-
const ErrorComponent = errorTestingUtils.createErrorThrowingComponent(
|
|
492
|
-
'DataTable interaction error',
|
|
493
|
-
'click'
|
|
494
|
-
);
|
|
495
|
-
|
|
496
|
-
renderWithProviders(
|
|
497
|
-
<TestErrorBoundary>
|
|
498
|
-
<ErrorComponent />
|
|
499
|
-
</TestErrorBoundary>
|
|
500
|
-
);
|
|
501
|
-
|
|
502
|
-
await user.click(screen.getByTestId('error-button'));
|
|
503
|
-
|
|
504
|
-
await waitFor(() => {
|
|
505
|
-
expect(screen.getByTestId('error-display')).toBeInTheDocument();
|
|
506
|
-
});
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
it('should recover from errors when props change', async () => {
|
|
510
|
-
const TestComponent = ({ shouldError }: { shouldError: boolean }) => {
|
|
511
|
-
if (shouldError) {
|
|
512
|
-
throw new Error('DataTable prop error');
|
|
513
|
-
}
|
|
514
|
-
return <div>Normal content</div>;
|
|
515
|
-
};
|
|
516
|
-
|
|
517
|
-
await errorTestingUtils.testErrorRecovery(
|
|
518
|
-
TestComponent,
|
|
519
|
-
{ shouldError: true },
|
|
520
|
-
{ shouldError: false }
|
|
521
|
-
);
|
|
522
|
-
|
|
523
|
-
expect(screen.getByText('Normal content')).toBeInTheDocument();
|
|
524
|
-
});
|
|
525
|
-
});
|
|
526
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file DataTable Header Component
|
|
3
|
-
* @package @jmruthers/pace-core
|
|
4
|
-
* @module Components/DataTable/Components
|
|
5
|
-
* @since 0.2.0
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import { cn } from '../../../utils/cn';
|
|
10
|
-
|
|
11
|
-
export interface DataTableHeaderProps {
|
|
12
|
-
title?: string;
|
|
13
|
-
description?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function DataTableHeader({ title, description }: DataTableHeaderProps) {
|
|
17
|
-
const hasTitle = !!title && title.trim().length > 0;
|
|
18
|
-
const hasDescription = !!description && description.trim().length > 0;
|
|
19
|
-
if (!hasTitle && !hasDescription) return null;
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<div className="pb-4">
|
|
23
|
-
{hasTitle && (
|
|
24
|
-
<h2 className="text-2xl font-bold tracking-tight break-words">{title}</h2>
|
|
25
|
-
)}
|
|
26
|
-
{hasDescription && (
|
|
27
|
-
<p className="text-muted-foreground mt-2 break-words">{description}</p>
|
|
28
|
-
)}
|
|
29
|
-
</div>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { screen } from '@testing-library/react';
|
|
3
|
-
import { describe, it, expect } from 'vitest';
|
|
4
|
-
import '@testing-library/jest-dom';
|
|
5
|
-
import { renderWithProviders } from '../../../../__tests__/shared';
|
|
6
|
-
import { DataTableHeader } from '../DataTableHeader';
|
|
7
|
-
|
|
8
|
-
describe('DataTableHeader Component', () => {
|
|
9
|
-
it('renders nothing when no title or description provided', () => {
|
|
10
|
-
renderWithProviders(<DataTableHeader />);
|
|
11
|
-
// Should render nothing when no title or description provided
|
|
12
|
-
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('renders only title when provided', () => {
|
|
16
|
-
renderWithProviders(<DataTableHeader title="My Data Table" />);
|
|
17
|
-
|
|
18
|
-
expect(screen.getByText('My Data Table')).toBeInTheDocument();
|
|
19
|
-
expect(screen.getByRole('heading', { level: 2 })).toBeInTheDocument();
|
|
20
|
-
expect(screen.queryByText('description')).not.toBeInTheDocument();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('renders only description when provided', () => {
|
|
24
|
-
renderWithProviders(<DataTableHeader description="This is a description" />);
|
|
25
|
-
|
|
26
|
-
expect(screen.getByText('This is a description')).toBeInTheDocument();
|
|
27
|
-
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('renders both title and description when provided', () => {
|
|
31
|
-
renderWithProviders(
|
|
32
|
-
<DataTableHeader
|
|
33
|
-
title="My Data Table"
|
|
34
|
-
description="This is a description"
|
|
35
|
-
/>
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
expect(screen.getByText('My Data Table')).toBeInTheDocument();
|
|
39
|
-
expect(screen.getByText('This is a description')).toBeInTheDocument();
|
|
40
|
-
expect(screen.getByRole('heading', { level: 2 })).toBeInTheDocument();
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('has correct styling classes for title', () => {
|
|
44
|
-
renderWithProviders(<DataTableHeader title="My Data Table" />);
|
|
45
|
-
|
|
46
|
-
const title = screen.getByRole('heading', { level: 2 });
|
|
47
|
-
expect(title).toHaveClass('text-2xl', 'font-bold', 'tracking-tight');
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('has correct styling classes for description', () => {
|
|
51
|
-
renderWithProviders(<DataTableHeader description="This is a description" />);
|
|
52
|
-
|
|
53
|
-
const description = screen.getByText('This is a description');
|
|
54
|
-
expect(description).toHaveClass('text-muted-foreground', 'mt-2');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('has correct container styling', () => {
|
|
58
|
-
renderWithProviders(<DataTableHeader title="My Data Table" />);
|
|
59
|
-
|
|
60
|
-
const container = screen.getByText('My Data Table').closest('div');
|
|
61
|
-
expect(container).toHaveClass('pb-4');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('handles empty string title', () => {
|
|
65
|
-
renderWithProviders(<DataTableHeader title="" />);
|
|
66
|
-
// Should render nothing when title is empty
|
|
67
|
-
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('handles empty string description', () => {
|
|
71
|
-
renderWithProviders(<DataTableHeader description="" />);
|
|
72
|
-
// Should render nothing when description is empty
|
|
73
|
-
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('handles both empty strings', () => {
|
|
77
|
-
renderWithProviders(<DataTableHeader title="" description="" />);
|
|
78
|
-
// Should render nothing when both title and description are empty
|
|
79
|
-
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('handles whitespace-only title', () => {
|
|
83
|
-
renderWithProviders(<DataTableHeader title=" " />);
|
|
84
|
-
// Should render nothing when title is only whitespace
|
|
85
|
-
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('handles whitespace-only description', () => {
|
|
89
|
-
renderWithProviders(<DataTableHeader description=" " />);
|
|
90
|
-
// Should render nothing when description is only whitespace
|
|
91
|
-
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('renders with long title text', () => {
|
|
95
|
-
const longTitle = 'This is a very long title that might wrap to multiple lines in the UI';
|
|
96
|
-
renderWithProviders(<DataTableHeader title={longTitle} />);
|
|
97
|
-
|
|
98
|
-
expect(screen.getByText(longTitle)).toBeInTheDocument();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('renders with long description text', () => {
|
|
102
|
-
const longDescription = 'This is a very long description that might wrap to multiple lines in the UI and should be handled gracefully';
|
|
103
|
-
renderWithProviders(<DataTableHeader description={longDescription} />);
|
|
104
|
-
|
|
105
|
-
expect(screen.getByText(longDescription)).toBeInTheDocument();
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('maintains consistent structure across re-renders', () => {
|
|
109
|
-
const { rerender } = renderWithProviders(
|
|
110
|
-
<DataTableHeader
|
|
111
|
-
title="Initial Title"
|
|
112
|
-
description="Initial Description"
|
|
113
|
-
/>
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
expect(screen.getByText('Initial Title')).toBeInTheDocument();
|
|
117
|
-
expect(screen.getByText('Initial Description')).toBeInTheDocument();
|
|
118
|
-
|
|
119
|
-
rerender(
|
|
120
|
-
<DataTableHeader
|
|
121
|
-
title="Updated Title"
|
|
122
|
-
description="Updated Description"
|
|
123
|
-
/>
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
expect(screen.getByText('Updated Title')).toBeInTheDocument();
|
|
127
|
-
expect(screen.getByText('Updated Description')).toBeInTheDocument();
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('handles special characters in title', () => {
|
|
131
|
-
const specialTitle = 'Title with special chars: !@#$%^&*()_+-=[]{}|;:,.<>?';
|
|
132
|
-
renderWithProviders(<DataTableHeader title={specialTitle} />);
|
|
133
|
-
|
|
134
|
-
expect(screen.getByText(specialTitle)).toBeInTheDocument();
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('handles special characters in description', () => {
|
|
138
|
-
const specialDescription = 'Description with special chars: !@#$%^&*()_+-=[]{}|;:,.<>?';
|
|
139
|
-
renderWithProviders(<DataTableHeader description={specialDescription} />);
|
|
140
|
-
|
|
141
|
-
expect(screen.getByText(specialDescription)).toBeInTheDocument();
|
|
142
|
-
});
|
|
143
|
-
});
|