@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.
Files changed (167) hide show
  1. package/dist/{DataTable-BHlzyKZP.d.ts → DataTable-C1AEm9Cx.d.ts} +1 -1
  2. package/dist/{DataTable-GEY5U7OI.js → DataTable-EEUDXPE5.js} +2 -8
  3. package/dist/{api-T6CBS7IO.js → api-ETQ6YJ3C.js} +2 -3
  4. package/dist/{chunk-DY5E3AT7.js → chunk-BEZRLNK3.js} +13 -3
  5. package/dist/chunk-BEZRLNK3.js.map +1 -0
  6. package/dist/{chunk-ANE4PDC2.js → chunk-C5G2A4PO.js} +159 -6
  7. package/dist/chunk-C5G2A4PO.js.map +1 -0
  8. package/dist/{chunk-WYB6MBZA.js → chunk-EWKPTNPO.js} +579 -973
  9. package/dist/chunk-EWKPTNPO.js.map +1 -0
  10. package/dist/{chunk-TMRLB2LA.js → chunk-HEMJ4SUJ.js} +2 -2
  11. package/dist/{chunk-O4T53L7X.js → chunk-HNDFPXUU.js} +5 -5
  12. package/dist/{chunk-UY7AM4QG.js → chunk-RRUYHORU.js} +161 -74
  13. package/dist/chunk-RRUYHORU.js.map +1 -0
  14. package/dist/{chunk-PFRRIDYA.js → chunk-TIVL4UQ7.js} +2 -2
  15. package/dist/{chunk-2MKP6IYD.js → chunk-VYG4AXYW.js} +2 -2
  16. package/dist/components.d.ts +2 -2
  17. package/dist/components.js +15 -16
  18. package/dist/components.js.map +1 -1
  19. package/dist/hooks.d.ts +1 -1
  20. package/dist/hooks.js +4 -4
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +16 -17
  23. package/dist/index.js.map +1 -1
  24. package/dist/providers.js +2 -2
  25. package/dist/rbac/index.js +25 -20
  26. package/dist/rbac/index.js.map +1 -1
  27. package/dist/styles/core.css +83 -62
  28. package/dist/{types-CInEi-ng.d.ts → types-DiRQsGJs.d.ts} +0 -2
  29. package/dist/utils.d.ts +2 -2
  30. package/dist/utils.js +1 -1
  31. package/docs/api/classes/ErrorBoundary.md +1 -1
  32. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  33. package/docs/api/interfaces/AggregateConfig.md +1 -1
  34. package/docs/api/interfaces/ButtonProps.md +1 -1
  35. package/docs/api/interfaces/CardProps.md +1 -1
  36. package/docs/api/interfaces/ColorPalette.md +1 -1
  37. package/docs/api/interfaces/ColorShade.md +1 -1
  38. package/docs/api/interfaces/DataTableAction.md +1 -1
  39. package/docs/api/interfaces/DataTableColumn.md +1 -1
  40. package/docs/api/interfaces/DataTableProps.md +33 -33
  41. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  42. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  43. package/docs/api/interfaces/EventContextType.md +1 -1
  44. package/docs/api/interfaces/EventLogoProps.md +1 -1
  45. package/docs/api/interfaces/EventProviderProps.md +1 -1
  46. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  47. package/docs/api/interfaces/FileUploadProps.md +1 -1
  48. package/docs/api/interfaces/FooterProps.md +1 -1
  49. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  50. package/docs/api/interfaces/InputProps.md +1 -1
  51. package/docs/api/interfaces/LabelProps.md +1 -1
  52. package/docs/api/interfaces/LoginFormProps.md +1 -1
  53. package/docs/api/interfaces/NavigationItem.md +1 -1
  54. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  55. package/docs/api/interfaces/Organisation.md +1 -1
  56. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  57. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  58. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  59. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  60. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  61. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  62. package/docs/api/interfaces/PaletteData.md +1 -1
  63. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  64. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  65. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  66. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  67. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  68. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  69. package/docs/api/interfaces/StorageConfig.md +1 -1
  70. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  71. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  72. package/docs/api/interfaces/StorageListOptions.md +1 -1
  73. package/docs/api/interfaces/StorageListResult.md +1 -1
  74. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  75. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  76. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  77. package/docs/api/interfaces/StyleImport.md +1 -1
  78. package/docs/api/interfaces/ToastActionElement.md +1 -1
  79. package/docs/api/interfaces/ToastProps.md +1 -1
  80. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  81. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  82. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  83. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  84. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  85. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  86. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  87. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  88. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  89. package/docs/api/interfaces/UserEventAccess.md +1 -1
  90. package/docs/api/interfaces/UserMenuProps.md +1 -1
  91. package/docs/api/interfaces/UserProfile.md +1 -1
  92. package/docs/api/modules.md +10 -10
  93. package/docs/architecture/README.md +1 -1
  94. package/package.json +1 -1
  95. package/src/__tests__/shared/testUtils.optimized.tsx +65 -7
  96. package/src/components/DataTable/DataTable.tsx +1 -3
  97. package/src/components/DataTable/__tests__/DataTable.errorHandling.test.tsx +0 -8
  98. package/src/components/DataTable/__tests__/DataTable.hierarchical.test.tsx +17 -12
  99. package/src/components/DataTable/__tests__/DataTable.infinite-loop.test.tsx +0 -1
  100. package/src/components/DataTable/__tests__/DataTable.integration.test.tsx +4 -12
  101. package/src/components/DataTable/__tests__/DataTable.performance.test.tsx +0 -8
  102. package/src/components/DataTable/__tests__/DataTable.permissions.test.tsx +21 -11
  103. package/src/components/DataTable/__tests__/DataTable.sorting.test.tsx +321 -0
  104. package/src/components/DataTable/__tests__/DataTable.userWorkflows.test.tsx +21 -11
  105. package/src/components/DataTable/__tests__/DataTable.workflowValidation.test.tsx +94 -0
  106. package/src/components/DataTable/__tests__/DataTable.workflows.test.tsx +25 -15
  107. package/src/components/DataTable/__tests__/README.md +11 -2
  108. package/src/components/DataTable/__tests__/performance-regression.test.tsx +0 -11
  109. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +0 -1
  110. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +2 -2
  111. package/src/components/DataTable/components/DataTableBody.tsx +34 -35
  112. package/src/components/DataTable/components/DataTableCore.tsx +205 -133
  113. package/src/components/DataTable/components/DataTableToolbar.tsx +9 -10
  114. package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -7
  115. package/src/components/DataTable/components/EditableRow.tsx +6 -7
  116. package/src/components/DataTable/components/FilterRow.tsx +0 -1
  117. package/src/components/DataTable/components/GroupingDropdown.tsx +2 -2
  118. package/src/components/DataTable/components/UnifiedTableBody.tsx +83 -281
  119. package/src/components/DataTable/components/VirtualizedDataTable.tsx +9 -89
  120. package/src/components/DataTable/components/__tests__/DataTable.accessibility.test.tsx +111 -5
  121. package/src/components/DataTable/components/__tests__/DataTable.integration.test.tsx +82 -13
  122. package/src/components/DataTable/components/__tests__/DataTable.performance.test.tsx +0 -1
  123. package/src/components/DataTable/components/__tests__/DataTable.real.test.tsx +2 -2
  124. package/src/components/DataTable/components/__tests__/DataTable.security.test.tsx +0 -1
  125. package/src/components/DataTable/components/__tests__/DataTable.unit.test.tsx +2 -2
  126. package/src/components/DataTable/components/__tests__/FilteringToggle.unit.test.tsx +3 -0
  127. package/src/components/DataTable/components/index.ts +0 -1
  128. package/src/components/DataTable/core/DataTableContext.tsx +0 -1
  129. package/src/components/DataTable/index.ts +0 -2
  130. package/src/components/DataTable/types.ts +0 -2
  131. package/src/components/Input/Input.tsx +2 -2
  132. package/src/components/Input/__tests__/Input.unit.test.tsx +4 -4
  133. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -2
  134. package/src/components/RBAC/PagePermissionGuard.tsx +13 -0
  135. package/src/components/RBAC/__tests__/PagePermissionGuard.unit.test.tsx +10 -1
  136. package/src/components/Select/Select.tsx +7 -1
  137. package/src/components/__tests__/EdgeCaseTesting.enhanced.test.tsx +2 -1
  138. package/src/hooks/__tests__/useRBAC.unit.test.ts +32 -24
  139. package/src/providers/RBACProvider.tsx +14 -2
  140. package/src/providers/__tests__/UnifiedAuthProvider.unit.test.tsx +11 -3
  141. package/src/rbac/__tests__/cache-invalidation.test.ts +2 -2
  142. package/src/rbac/__tests__/cache.test.ts +3 -3
  143. package/src/rbac/hooks.ts +15 -7
  144. package/src/styles/core.css +83 -62
  145. package/src/utils/__tests__/lazyLoad.unit.test.tsx +13 -18
  146. package/src/utils/storage/__tests__/helpers.unit.test.ts +9 -7
  147. package/dist/cache-I72HKDOA.js +0 -12
  148. package/dist/cache-I72HKDOA.js.map +0 -1
  149. package/dist/chunk-ANE4PDC2.js.map +0 -1
  150. package/dist/chunk-DY5E3AT7.js.map +0 -1
  151. package/dist/chunk-MRRFJ6SA.js +0 -161
  152. package/dist/chunk-MRRFJ6SA.js.map +0 -1
  153. package/dist/chunk-UY7AM4QG.js.map +0 -1
  154. package/dist/chunk-WYB6MBZA.js.map +0 -1
  155. package/src/components/DataTable/__tests__/DataTable.autoSizing.test.tsx +0 -526
  156. package/src/components/DataTable/components/DataTableHeader.tsx +0 -31
  157. package/src/components/DataTable/components/__tests__/DataTableHeader.unit.test.tsx +0 -143
  158. package/src/components/DataTable/examples/AutoSizingExample.tsx +0 -180
  159. package/src/components/DataTable/examples/ColumnSizingComparison.tsx +0 -235
  160. package/src/components/DataTable/utils/__tests__/columnSizing.test.ts +0 -237
  161. package/src/components/DataTable/utils/columnSizing.ts +0 -125
  162. /package/dist/{DataTable-GEY5U7OI.js.map → DataTable-EEUDXPE5.js.map} +0 -0
  163. /package/dist/{api-T6CBS7IO.js.map → api-ETQ6YJ3C.js.map} +0 -0
  164. /package/dist/{chunk-TMRLB2LA.js.map → chunk-HEMJ4SUJ.js.map} +0 -0
  165. /package/dist/{chunk-O4T53L7X.js.map → chunk-HNDFPXUU.js.map} +0 -0
  166. /package/dist/{chunk-PFRRIDYA.js.map → chunk-TIVL4UQ7.js.map} +0 -0
  167. /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
- });