@jmruthers/pace-core 0.5.117 → 0.5.119

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-ZOAKQ3SU.js → DataTable-BQYGKVHR.js} +6 -6
  2. package/dist/{UnifiedAuthProvider-YFN7YGVN.js → UnifiedAuthProvider-UACKFATV.js} +3 -3
  3. package/dist/{chunk-XN2LYHDI.js → chunk-B4GZ2BXO.js} +27 -8
  4. package/dist/{chunk-XN2LYHDI.js.map → chunk-B4GZ2BXO.js.map} +1 -1
  5. package/dist/{chunk-KA3PSVNV.js → chunk-BHWIUEYH.js} +2 -1
  6. package/dist/chunk-BHWIUEYH.js.map +1 -0
  7. package/dist/{chunk-LFS45U62.js → chunk-CGURJ27Z.js} +2 -2
  8. package/dist/{chunk-PHDAXDHB.js → chunk-D6BOFXYR.js} +3 -3
  9. package/dist/{chunk-2LM4QQGH.js → chunk-F7COHU5B.js} +8 -8
  10. package/dist/{chunk-P3PUOL6B.js → chunk-FKFHZUGF.js} +4 -4
  11. package/dist/{chunk-UKZWNQMB.js → chunk-NP5VABFV.js} +4 -4
  12. package/dist/{chunk-O3FTRYEU.js → chunk-NZ32EONV.js} +2 -2
  13. package/dist/{chunk-ECOVPXYS.js → chunk-RIEJGKD3.js} +4 -4
  14. package/dist/{chunk-IZXS7RZK.js → chunk-TDNI6ZWL.js} +5 -5
  15. package/dist/{chunk-VN3OOE35.js → chunk-ZYJ6O5CA.js} +2 -2
  16. package/dist/components.js +8 -8
  17. package/dist/hooks.js +7 -7
  18. package/dist/index.js +11 -11
  19. package/dist/providers.js +2 -2
  20. package/dist/rbac/index.js +7 -7
  21. package/dist/utils.js +1 -1
  22. package/docs/api/classes/ColumnFactory.md +1 -1
  23. package/docs/api/classes/ErrorBoundary.md +1 -1
  24. package/docs/api/classes/InvalidScopeError.md +1 -1
  25. package/docs/api/classes/MissingUserContextError.md +1 -1
  26. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  27. package/docs/api/classes/PermissionDeniedError.md +1 -1
  28. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  29. package/docs/api/classes/RBACAuditManager.md +1 -1
  30. package/docs/api/classes/RBACCache.md +1 -1
  31. package/docs/api/classes/RBACEngine.md +1 -1
  32. package/docs/api/classes/RBACError.md +1 -1
  33. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  34. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  35. package/docs/api/classes/StorageUtils.md +1 -1
  36. package/docs/api/enums/FileCategory.md +1 -1
  37. package/docs/api/interfaces/AggregateConfig.md +1 -1
  38. package/docs/api/interfaces/ButtonProps.md +1 -1
  39. package/docs/api/interfaces/CardProps.md +1 -1
  40. package/docs/api/interfaces/ColorPalette.md +1 -1
  41. package/docs/api/interfaces/ColorShade.md +1 -1
  42. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  43. package/docs/api/interfaces/DataRecord.md +1 -1
  44. package/docs/api/interfaces/DataTableAction.md +1 -1
  45. package/docs/api/interfaces/DataTableColumn.md +1 -1
  46. package/docs/api/interfaces/DataTableProps.md +1 -1
  47. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  48. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  49. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  50. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  51. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  52. package/docs/api/interfaces/FileMetadata.md +1 -1
  53. package/docs/api/interfaces/FileReference.md +1 -1
  54. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  55. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  56. package/docs/api/interfaces/FileUploadProps.md +1 -1
  57. package/docs/api/interfaces/FooterProps.md +1 -1
  58. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  59. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  60. package/docs/api/interfaces/InputProps.md +1 -1
  61. package/docs/api/interfaces/LabelProps.md +1 -1
  62. package/docs/api/interfaces/LoginFormProps.md +1 -1
  63. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  64. package/docs/api/interfaces/NavigationContextType.md +1 -1
  65. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  66. package/docs/api/interfaces/NavigationItem.md +1 -1
  67. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  68. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  69. package/docs/api/interfaces/Organisation.md +1 -1
  70. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  71. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  72. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  73. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  74. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  75. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  76. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  77. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  78. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  79. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  80. package/docs/api/interfaces/PaletteData.md +1 -1
  81. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  82. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  83. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  84. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  85. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  86. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  87. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  88. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  89. package/docs/api/interfaces/RBACConfig.md +1 -1
  90. package/docs/api/interfaces/RBACLogger.md +1 -1
  91. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  92. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  93. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  94. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  95. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  96. package/docs/api/interfaces/RouteConfig.md +1 -1
  97. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  98. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  99. package/docs/api/interfaces/StorageConfig.md +1 -1
  100. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  101. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  102. package/docs/api/interfaces/StorageListOptions.md +1 -1
  103. package/docs/api/interfaces/StorageListResult.md +1 -1
  104. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  105. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  106. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  107. package/docs/api/interfaces/StyleImport.md +1 -1
  108. package/docs/api/interfaces/SwitchProps.md +1 -1
  109. package/docs/api/interfaces/ToastActionElement.md +1 -1
  110. package/docs/api/interfaces/ToastProps.md +1 -1
  111. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  112. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  113. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  114. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  115. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  116. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  117. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  118. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  119. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  120. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  121. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  122. package/docs/api/interfaces/UserEventAccess.md +1 -1
  123. package/docs/api/interfaces/UserMenuProps.md +1 -1
  124. package/docs/api/interfaces/UserProfile.md +1 -1
  125. package/docs/api/modules.md +2 -2
  126. package/package.json +1 -1
  127. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +697 -0
  128. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +544 -9
  129. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +1004 -0
  130. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +612 -0
  131. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +266 -0
  132. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +455 -1
  133. package/src/hooks/__tests__/index.unit.test.ts +223 -0
  134. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +748 -0
  135. package/src/hooks/__tests__/useEvents.unit.test.ts +249 -0
  136. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +1060 -0
  137. package/src/hooks/__tests__/useFileUrl.unit.test.ts +958 -0
  138. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +540 -1
  139. package/src/hooks/__tests__/useIsMobile.unit.test.ts +205 -5
  140. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +616 -1
  141. package/src/hooks/__tests__/useOrganisations.unit.test.ts +369 -0
  142. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +608 -0
  143. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +2 -0
  144. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +372 -0
  145. package/src/hooks/__tests__/useToast.unit.test.tsx +431 -30
  146. package/src/hooks/useSecureDataAccess.test.ts +1 -0
  147. package/src/hooks/useSecureDataAccess.ts +43 -5
  148. package/src/rbac/audit-enhanced.ts +339 -0
  149. package/src/services/EventService.ts +1 -0
  150. package/src/services/__tests__/AuthService.test.ts +473 -0
  151. package/src/services/__tests__/EventService.test.ts +390 -0
  152. package/src/services/__tests__/InactivityService.test.ts +217 -0
  153. package/src/services/__tests__/OrganisationService.test.ts +371 -0
  154. package/dist/chunk-KA3PSVNV.js.map +0 -1
  155. package/src/components/DataTable/utils/debugTools.ts +0 -609
  156. package/src/rbac/testing/index.tsx +0 -340
  157. /package/dist/{DataTable-ZOAKQ3SU.js.map → DataTable-BQYGKVHR.js.map} +0 -0
  158. /package/dist/{UnifiedAuthProvider-YFN7YGVN.js.map → UnifiedAuthProvider-UACKFATV.js.map} +0 -0
  159. /package/dist/{chunk-LFS45U62.js.map → chunk-CGURJ27Z.js.map} +0 -0
  160. /package/dist/{chunk-PHDAXDHB.js.map → chunk-D6BOFXYR.js.map} +0 -0
  161. /package/dist/{chunk-2LM4QQGH.js.map → chunk-F7COHU5B.js.map} +0 -0
  162. /package/dist/{chunk-P3PUOL6B.js.map → chunk-FKFHZUGF.js.map} +0 -0
  163. /package/dist/{chunk-UKZWNQMB.js.map → chunk-NP5VABFV.js.map} +0 -0
  164. /package/dist/{chunk-O3FTRYEU.js.map → chunk-NZ32EONV.js.map} +0 -0
  165. /package/dist/{chunk-ECOVPXYS.js.map → chunk-RIEJGKD3.js.map} +0 -0
  166. /package/dist/{chunk-IZXS7RZK.js.map → chunk-TDNI6ZWL.js.map} +0 -0
  167. /package/dist/{chunk-VN3OOE35.js.map → chunk-ZYJ6O5CA.js.map} +0 -0
@@ -798,4 +798,701 @@ describe('DataTableCore Component', () => {
798
798
  expect(screen.getByText('User 1')).toBeInTheDocument();
799
799
  });
800
800
  });
801
+
802
+ describe('Event Handlers', () => {
803
+ it('calls onEditRow when row is edited', async () => {
804
+ const user = userEvent.setup();
805
+ const onEditRow = vi.fn();
806
+ const features = createDefaultFeatures();
807
+ features.editing = true;
808
+
809
+ const { useDataTableState } = await import('../hooks/useDataTableState');
810
+ vi.mocked(useDataTableState).mockReturnValueOnce({
811
+ state: {
812
+ sorting: [],
813
+ columnFilters: [],
814
+ columnVisibility: {},
815
+ grouping: [],
816
+ expanded: {},
817
+ pagination: { pageIndex: 0, pageSize: 10 },
818
+ columnOrder: [],
819
+ rowSelection: {},
820
+ isCreating: false,
821
+ creationData: {},
822
+ editingRowId: 'user-1',
823
+ editingData: { name: 'Edited Name' },
824
+ showImportModal: false,
825
+ showFilterRow: false,
826
+ searchQuery: '',
827
+ },
828
+ actions: {
829
+ setSorting: vi.fn(),
830
+ setColumnFilters: vi.fn(),
831
+ setColumnVisibility: vi.fn(),
832
+ setGrouping: vi.fn(),
833
+ setExpanded: vi.fn(),
834
+ setPagination: vi.fn(),
835
+ setColumnOrder: vi.fn(),
836
+ setRowSelection: vi.fn(),
837
+ setCreating: vi.fn(),
838
+ setCreationData: vi.fn(),
839
+ clearCreationData: vi.fn(),
840
+ setEditingRow: vi.fn(),
841
+ clearEditing: vi.fn(),
842
+ setImportModal: vi.fn(),
843
+ setFilterRow: vi.fn(),
844
+ setSearchQuery: vi.fn(),
845
+ resetState: vi.fn(),
846
+ },
847
+ });
848
+
849
+ render(
850
+ <DataTableCore
851
+ data={mockData}
852
+ columns={mockColumns}
853
+ rbac={mockRBAC}
854
+ features={features}
855
+ onEditRow={onEditRow}
856
+ performance={mockPerformance}
857
+ />
858
+ );
859
+
860
+ // Simulate save editing
861
+ // Note: This would require interacting with the EditableRow component
862
+ expect(screen.getByText('User 1')).toBeInTheDocument();
863
+ });
864
+
865
+ it('calls onDeleteRow when row is deleted', async () => {
866
+ const onDeleteRow = vi.fn();
867
+ const features = createDefaultFeatures();
868
+ features.deletion = true;
869
+
870
+ render(
871
+ <DataTableCore
872
+ data={mockData}
873
+ columns={mockColumns}
874
+ rbac={mockRBAC}
875
+ features={features}
876
+ onDeleteRow={onDeleteRow}
877
+ performance={mockPerformance}
878
+ />
879
+ );
880
+
881
+ expect(screen.getByText('User 1')).toBeInTheDocument();
882
+ });
883
+
884
+ it('calls onCreateRow when new row is created', async () => {
885
+ const onCreateRow = vi.fn();
886
+ const features = createDefaultFeatures();
887
+ features.creation = true;
888
+
889
+ const { useDataTableState } = await import('../hooks/useDataTableState');
890
+ vi.mocked(useDataTableState).mockReturnValueOnce({
891
+ state: {
892
+ sorting: [],
893
+ columnFilters: [],
894
+ columnVisibility: {},
895
+ grouping: [],
896
+ expanded: {},
897
+ pagination: { pageIndex: 0, pageSize: 10 },
898
+ columnOrder: [],
899
+ rowSelection: {},
900
+ isCreating: true,
901
+ creationData: { name: 'New User', email: 'new@example.com' },
902
+ editingRowId: null,
903
+ editingData: {},
904
+ showImportModal: false,
905
+ showFilterRow: false,
906
+ searchQuery: '',
907
+ },
908
+ actions: {
909
+ setSorting: vi.fn(),
910
+ setColumnFilters: vi.fn(),
911
+ setColumnVisibility: vi.fn(),
912
+ setGrouping: vi.fn(),
913
+ setExpanded: vi.fn(),
914
+ setPagination: vi.fn(),
915
+ setColumnOrder: vi.fn(),
916
+ setRowSelection: vi.fn(),
917
+ setCreating: vi.fn(),
918
+ setCreationData: vi.fn(),
919
+ clearCreationData: vi.fn(),
920
+ setEditingRow: vi.fn(),
921
+ clearEditing: vi.fn(),
922
+ setImportModal: vi.fn(),
923
+ setFilterRow: vi.fn(),
924
+ setSearchQuery: vi.fn(),
925
+ resetState: vi.fn(),
926
+ },
927
+ });
928
+
929
+ render(
930
+ <DataTableCore
931
+ data={mockData}
932
+ columns={mockColumns}
933
+ rbac={mockRBAC}
934
+ features={features}
935
+ onCreateRow={onCreateRow}
936
+ performance={mockPerformance}
937
+ />
938
+ );
939
+
940
+ expect(screen.getByText('User 1')).toBeInTheDocument();
941
+ });
942
+
943
+ it('calls onRowSelectionChange when row selection changes', async () => {
944
+ const onRowSelectionChange = vi.fn();
945
+ const features = createDefaultFeatures();
946
+ features.selection = true;
947
+
948
+ render(
949
+ <DataTableCore
950
+ data={mockData}
951
+ columns={mockColumns}
952
+ rbac={mockRBAC}
953
+ features={features}
954
+ onRowSelectionChange={onRowSelectionChange}
955
+ performance={mockPerformance}
956
+ />
957
+ );
958
+
959
+ expect(screen.getByText('User 1')).toBeInTheDocument();
960
+ });
961
+
962
+ it('calls onDeleteSelected when selected rows are deleted', async () => {
963
+ const onDeleteSelected = vi.fn();
964
+ const features = createDefaultFeatures();
965
+ features.deletion = true;
966
+ features.deleteSelected = true;
967
+
968
+ render(
969
+ <DataTableCore
970
+ data={mockData}
971
+ columns={mockColumns}
972
+ rbac={mockRBAC}
973
+ features={features}
974
+ onDeleteSelected={onDeleteSelected}
975
+ performance={mockPerformance}
976
+ />
977
+ );
978
+
979
+ expect(screen.getByText('User 1')).toBeInTheDocument();
980
+ });
981
+ });
982
+
983
+ describe('Export/Import Functionality', () => {
984
+ it('handles export when export feature is enabled', async () => {
985
+ const user = userEvent.setup();
986
+ const features = createDefaultFeatures();
987
+ features.export = true;
988
+
989
+ render(
990
+ <DataTableCore
991
+ data={mockData}
992
+ columns={mockColumns}
993
+ rbac={mockRBAC}
994
+ features={features}
995
+ performance={mockPerformance}
996
+ />
997
+ );
998
+
999
+ // Export button should be available
1000
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1001
+ });
1002
+
1003
+ it('handles import when import feature is enabled', async () => {
1004
+ const user = userEvent.setup();
1005
+ const onImport = vi.fn();
1006
+ const features = createDefaultFeatures();
1007
+ features.import = true;
1008
+
1009
+ const { useDataTableState } = await import('../hooks/useDataTableState');
1010
+ vi.mocked(useDataTableState).mockReturnValueOnce({
1011
+ state: {
1012
+ sorting: [],
1013
+ columnFilters: [],
1014
+ columnVisibility: {},
1015
+ grouping: [],
1016
+ expanded: {},
1017
+ pagination: { pageIndex: 0, pageSize: 10 },
1018
+ columnOrder: [],
1019
+ rowSelection: {},
1020
+ isCreating: false,
1021
+ creationData: {},
1022
+ editingRowId: null,
1023
+ editingData: {},
1024
+ showImportModal: true,
1025
+ showFilterRow: false,
1026
+ searchQuery: '',
1027
+ },
1028
+ actions: {
1029
+ setSorting: vi.fn(),
1030
+ setColumnFilters: vi.fn(),
1031
+ setColumnVisibility: vi.fn(),
1032
+ setGrouping: vi.fn(),
1033
+ setExpanded: vi.fn(),
1034
+ setPagination: vi.fn(),
1035
+ setColumnOrder: vi.fn(),
1036
+ setRowSelection: vi.fn(),
1037
+ setCreating: vi.fn(),
1038
+ setCreationData: vi.fn(),
1039
+ clearCreationData: vi.fn(),
1040
+ setEditingRow: vi.fn(),
1041
+ clearEditing: vi.fn(),
1042
+ setImportModal: vi.fn(),
1043
+ setFilterRow: vi.fn(),
1044
+ setSearchQuery: vi.fn(),
1045
+ resetState: vi.fn(),
1046
+ },
1047
+ });
1048
+
1049
+ render(
1050
+ <DataTableCore
1051
+ data={mockData}
1052
+ columns={mockColumns}
1053
+ rbac={mockRBAC}
1054
+ features={features}
1055
+ onImport={onImport}
1056
+ performance={mockPerformance}
1057
+ />
1058
+ );
1059
+
1060
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1061
+ });
1062
+ });
1063
+
1064
+ describe('Column Operations', () => {
1065
+ it('handles column visibility changes', () => {
1066
+ const features = createDefaultFeatures();
1067
+ features.columnVisibility = true;
1068
+
1069
+ render(
1070
+ <DataTableCore
1071
+ data={mockData}
1072
+ columns={mockColumns}
1073
+ rbac={mockRBAC}
1074
+ features={features}
1075
+ performance={mockPerformance}
1076
+ />
1077
+ );
1078
+
1079
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1080
+ });
1081
+
1082
+ it('handles column reordering when enabled', () => {
1083
+ const features = createDefaultFeatures();
1084
+ features.columnReordering = true;
1085
+
1086
+ render(
1087
+ <DataTableCore
1088
+ data={mockData}
1089
+ columns={mockColumns}
1090
+ rbac={mockRBAC}
1091
+ features={features}
1092
+ performance={mockPerformance}
1093
+ />
1094
+ );
1095
+
1096
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1097
+ });
1098
+
1099
+ it('handles column order persistence', () => {
1100
+ const features = createDefaultFeatures();
1101
+ features.columnReordering = true;
1102
+
1103
+ render(
1104
+ <DataTableCore
1105
+ data={mockData}
1106
+ columns={mockColumns}
1107
+ rbac={mockRBAC}
1108
+ features={features}
1109
+ storageKey="test-table"
1110
+ performance={mockPerformance}
1111
+ />
1112
+ );
1113
+
1114
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1115
+ });
1116
+ });
1117
+
1118
+ describe('State Management', () => {
1119
+ it('handles default sorting state', () => {
1120
+ const defaultSorting = [{ id: 'name', desc: false }];
1121
+
1122
+ render(
1123
+ <DataTableCore
1124
+ data={mockData}
1125
+ columns={mockColumns}
1126
+ rbac={mockRBAC}
1127
+ features={createDefaultFeatures()}
1128
+ defaultSorting={defaultSorting}
1129
+ performance={mockPerformance}
1130
+ />
1131
+ );
1132
+
1133
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1134
+ });
1135
+
1136
+ it('handles default grouping state', () => {
1137
+ const defaultGrouping = ['department'];
1138
+
1139
+ render(
1140
+ <DataTableCore
1141
+ data={mockData}
1142
+ columns={mockColumns}
1143
+ rbac={mockRBAC}
1144
+ features={createDefaultFeatures()}
1145
+ defaultGrouping={defaultGrouping}
1146
+ performance={mockPerformance}
1147
+ />
1148
+ );
1149
+
1150
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1151
+ });
1152
+
1153
+ it('handles initial page size', () => {
1154
+ render(
1155
+ <DataTableCore
1156
+ data={mockData}
1157
+ columns={mockColumns}
1158
+ rbac={mockRBAC}
1159
+ features={createDefaultFeatures()}
1160
+ initialPageSize={25}
1161
+ performance={mockPerformance}
1162
+ />
1163
+ );
1164
+
1165
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1166
+ });
1167
+
1168
+ it('handles controlled selection state', () => {
1169
+ const selection = { 'user-1': true, 'user-2': false };
1170
+
1171
+ render(
1172
+ <DataTableCore
1173
+ data={mockData}
1174
+ columns={mockColumns}
1175
+ rbac={mockRBAC}
1176
+ features={createDefaultFeatures()}
1177
+ selection={selection}
1178
+ performance={mockPerformance}
1179
+ />
1180
+ );
1181
+
1182
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1183
+ });
1184
+ });
1185
+
1186
+ describe('Server-Side Features', () => {
1187
+ it('handles server-side pagination mode', () => {
1188
+ const serverSide = {
1189
+ fetchData: vi.fn().mockResolvedValue({ data: mockData, totalCount: 100 }),
1190
+ totalCount: 100,
1191
+ };
1192
+
1193
+ render(
1194
+ <DataTableCore
1195
+ data={mockData}
1196
+ columns={mockColumns}
1197
+ rbac={mockRBAC}
1198
+ features={createDefaultFeatures()}
1199
+ serverSide={serverSide}
1200
+ paginationMode="server"
1201
+ performance={mockPerformance}
1202
+ />
1203
+ );
1204
+
1205
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1206
+ });
1207
+
1208
+ it('handles server-side data fetching', async () => {
1209
+ const serverSide = {
1210
+ fetchData: vi.fn().mockResolvedValue({ data: mockData, totalCount: 100 }),
1211
+ totalCount: 100,
1212
+ };
1213
+
1214
+ render(
1215
+ <DataTableCore
1216
+ data={mockData}
1217
+ columns={mockColumns}
1218
+ rbac={mockRBAC}
1219
+ features={createDefaultFeatures()}
1220
+ serverSide={serverSide}
1221
+ paginationMode="server"
1222
+ performance={mockPerformance}
1223
+ />
1224
+ );
1225
+
1226
+ await waitFor(() => {
1227
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1228
+ });
1229
+ });
1230
+ });
1231
+
1232
+ describe('Hierarchical Data', () => {
1233
+ it('handles hierarchical data when enabled', () => {
1234
+ const hierarchicalData = [
1235
+ { id: '1', name: 'Parent', isParent: true },
1236
+ { id: '2', name: 'Child', isParent: false, parentId: '1' },
1237
+ ];
1238
+ const features = createDefaultFeatures();
1239
+ features.hierarchical = true;
1240
+
1241
+ const hierarchical = {
1242
+ enabled: true,
1243
+ indentSize: 24,
1244
+ };
1245
+
1246
+ render(
1247
+ <DataTableCore
1248
+ data={hierarchicalData as any}
1249
+ columns={mockColumns}
1250
+ rbac={mockRBAC}
1251
+ features={features}
1252
+ hierarchical={hierarchical}
1253
+ performance={mockPerformance}
1254
+ />
1255
+ );
1256
+
1257
+ expect(screen.getByText('Parent')).toBeInTheDocument();
1258
+ });
1259
+ });
1260
+
1261
+ describe('Aggregates', () => {
1262
+ it('handles aggregate configurations', () => {
1263
+ const aggregates = [
1264
+ {
1265
+ columnId: 'age',
1266
+ type: 'average' as const,
1267
+ },
1268
+ ];
1269
+
1270
+ render(
1271
+ <DataTableCore
1272
+ data={mockData}
1273
+ columns={mockColumns}
1274
+ rbac={mockRBAC}
1275
+ features={createDefaultFeatures()}
1276
+ aggregates={aggregates}
1277
+ performance={mockPerformance}
1278
+ />
1279
+ );
1280
+
1281
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1282
+ });
1283
+ });
1284
+
1285
+ describe('Error Handling', () => {
1286
+ it('handles loading state correctly', () => {
1287
+ render(
1288
+ <DataTableCore
1289
+ data={mockData}
1290
+ columns={mockColumns}
1291
+ rbac={mockRBAC}
1292
+ features={createDefaultFeatures()}
1293
+ isLoading={true}
1294
+ performance={mockPerformance}
1295
+ />
1296
+ );
1297
+
1298
+ expect(screen.getByText('Loading...')).toBeInTheDocument();
1299
+ });
1300
+
1301
+ it('handles permission loading state', () => {
1302
+ mockUseDataTablePermissions.mockReturnValueOnce({
1303
+ permissions: {
1304
+ canRead: { can: true, isLoading: true },
1305
+ canCreate: { can: true, isLoading: false },
1306
+ canUpdate: { can: true, isLoading: false },
1307
+ canDelete: { can: true, isLoading: false },
1308
+ canExport: { can: true, isLoading: false },
1309
+ canImport: { can: true, isLoading: false },
1310
+ },
1311
+ secureFeatures: createFullFeatures(),
1312
+ effectivePageId: 'test-page',
1313
+ });
1314
+
1315
+ render(
1316
+ <DataTableCore
1317
+ data={mockData}
1318
+ columns={mockColumns}
1319
+ rbac={mockRBAC}
1320
+ features={createDefaultFeatures()}
1321
+ performance={mockPerformance}
1322
+ />
1323
+ );
1324
+
1325
+ // When permissions are loading, the component should still render
1326
+ // The loading state might be handled differently or the component
1327
+ // might render normally while permissions load
1328
+ // Verify the component renders without error
1329
+ expect(screen.getByRole('table')).toBeInTheDocument();
1330
+
1331
+ // Restore mock
1332
+ mockUseDataTablePermissions.mockReturnValue({
1333
+ permissions: {
1334
+ canRead: { can: true, isLoading: false },
1335
+ canCreate: { can: true, isLoading: false },
1336
+ canUpdate: { can: true, isLoading: false },
1337
+ canDelete: { can: true, isLoading: false },
1338
+ canExport: { can: true, isLoading: false },
1339
+ canImport: { can: true, isLoading: false },
1340
+ },
1341
+ secureFeatures: createFullFeatures(),
1342
+ effectivePageId: 'test-page',
1343
+ });
1344
+ });
1345
+ });
1346
+
1347
+ describe('Layout Persistence', () => {
1348
+ it('calls onLayoutChange when layout changes', () => {
1349
+ const onLayoutChange = vi.fn();
1350
+ const features = createDefaultFeatures();
1351
+ features.columnVisibility = true;
1352
+ features.columnReordering = true;
1353
+
1354
+ render(
1355
+ <DataTableCore
1356
+ data={mockData}
1357
+ columns={mockColumns}
1358
+ rbac={mockRBAC}
1359
+ features={features}
1360
+ onLayoutChange={onLayoutChange}
1361
+ performance={mockPerformance}
1362
+ />
1363
+ );
1364
+
1365
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1366
+ });
1367
+ });
1368
+
1369
+ describe('Performance Features', () => {
1370
+ it('handles virtual scrolling for large datasets', () => {
1371
+ const largeData = testDataScenarios.large;
1372
+ const features = createDefaultFeatures();
1373
+ features.pagination = true;
1374
+
1375
+ render(
1376
+ <DataTableCore
1377
+ data={largeData}
1378
+ columns={mockColumns}
1379
+ rbac={mockRBAC}
1380
+ features={features}
1381
+ virtualHeight={600}
1382
+ performance={mockPerformance}
1383
+ />
1384
+ );
1385
+
1386
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1387
+ });
1388
+
1389
+ it('handles enhanced pagination when enabled', () => {
1390
+ const features = createDefaultFeatures();
1391
+ features.pagination = true;
1392
+
1393
+ render(
1394
+ <DataTableCore
1395
+ data={mockData}
1396
+ columns={mockColumns}
1397
+ rbac={mockRBAC}
1398
+ features={features}
1399
+ enhancedPagination={true}
1400
+ performance={mockPerformance}
1401
+ />
1402
+ );
1403
+
1404
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1405
+ });
1406
+ });
1407
+
1408
+ describe('Actions Configuration', () => {
1409
+ it('renders custom actions', () => {
1410
+ const actions = [
1411
+ {
1412
+ label: 'Custom Action',
1413
+ onClick: vi.fn(),
1414
+ testId: 'custom-action',
1415
+ },
1416
+ ];
1417
+
1418
+ render(
1419
+ <DataTableCore
1420
+ data={mockData}
1421
+ columns={mockColumns}
1422
+ rbac={mockRBAC}
1423
+ features={createDefaultFeatures()}
1424
+ actions={actions}
1425
+ performance={mockPerformance}
1426
+ />
1427
+ );
1428
+
1429
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1430
+ });
1431
+ });
1432
+
1433
+ describe('Edge Cases', () => {
1434
+ it('handles empty data array', () => {
1435
+ render(
1436
+ <DataTableCore
1437
+ data={[]}
1438
+ columns={mockColumns}
1439
+ rbac={mockRBAC}
1440
+ features={createDefaultFeatures()}
1441
+ performance={mockPerformance}
1442
+ />
1443
+ );
1444
+
1445
+ expect(screen.getByText('No data available')).toBeInTheDocument();
1446
+ });
1447
+
1448
+ it('handles missing getRowId function', () => {
1449
+ render(
1450
+ <DataTableCore
1451
+ data={mockData}
1452
+ columns={mockColumns}
1453
+ rbac={mockRBAC}
1454
+ features={createDefaultFeatures()}
1455
+ getRowId={undefined}
1456
+ performance={mockPerformance}
1457
+ />
1458
+ );
1459
+
1460
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1461
+ });
1462
+
1463
+ it('handles custom getRowId function', () => {
1464
+ const getRowId = (row: any) => `custom-${row.id}`;
1465
+
1466
+ render(
1467
+ <DataTableCore
1468
+ data={mockData}
1469
+ columns={mockColumns}
1470
+ rbac={mockRBAC}
1471
+ features={createDefaultFeatures()}
1472
+ getRowId={getRowId}
1473
+ performance={mockPerformance}
1474
+ />
1475
+ );
1476
+
1477
+ expect(screen.getByText('User 1')).toBeInTheDocument();
1478
+ });
1479
+
1480
+ it('handles React element as emptyState', () => {
1481
+ const emptyStateElement = <div data-testid="custom-empty">Custom Empty</div>;
1482
+
1483
+ render(
1484
+ <DataTableCore
1485
+ data={[]}
1486
+ columns={mockColumns}
1487
+ rbac={mockRBAC}
1488
+ features={createDefaultFeatures()}
1489
+ emptyState={emptyStateElement}
1490
+ performance={mockPerformance}
1491
+ />
1492
+ );
1493
+
1494
+ // Component should render without error
1495
+ expect(screen.getByText('No data available')).toBeInTheDocument();
1496
+ });
1497
+ });
801
1498
  });