@jmruthers/pace-core 0.2.7 → 0.5.1
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-EEUDXPE5.js → DataTable-GX3XERFJ.js} +8 -4
- package/dist/{DataTable-C1AEm9Cx.d.ts → DataTable-ltTFXHS3.d.ts} +3 -1
- package/dist/{chunk-VYG4AXYW.js → chunk-5EL3KHOQ.js} +2 -2
- package/dist/{chunk-ETEJVKYK.js → chunk-6CR3MRZN.js} +1426 -62
- package/dist/chunk-6CR3MRZN.js.map +1 -0
- package/dist/chunk-AUE24LVR.js +268 -0
- package/dist/chunk-AUE24LVR.js.map +1 -0
- package/dist/chunk-COBPIXXQ.js +379 -0
- package/dist/chunk-COBPIXXQ.js.map +1 -0
- package/dist/{chunk-EWKPTNPO.js → chunk-GSNM5D6H.js} +388 -86
- package/dist/chunk-GSNM5D6H.js.map +1 -0
- package/dist/{chunk-2V3Y6YBC.js → chunk-OEGRKULD.js} +1 -42
- package/dist/chunk-OEGRKULD.js.map +1 -0
- package/dist/chunk-OYRY44Q2.js +62 -0
- package/dist/chunk-OYRY44Q2.js.map +1 -0
- package/dist/{chunk-RRUYHORU.js → chunk-T3XIA4AJ.js} +297 -433
- package/dist/chunk-T3XIA4AJ.js.map +1 -0
- package/dist/{chunk-HEMJ4SUJ.js → chunk-TGDCLPP2.js} +11 -7
- package/dist/{chunk-HEMJ4SUJ.js.map → chunk-TGDCLPP2.js.map} +1 -1
- package/dist/{chunk-HNDFPXUU.js → chunk-U6JDHVC2.js} +6 -4
- package/dist/{chunk-HNDFPXUU.js.map → chunk-U6JDHVC2.js.map} +1 -1
- package/dist/{chunk-TIVL4UQ7.js → chunk-XJK2J4N6.js} +6 -4
- package/dist/{chunk-TIVL4UQ7.js.map → chunk-XJK2J4N6.js.map} +1 -1
- package/dist/components.d.ts +2 -2
- package/dist/components.js +21 -20
- package/dist/components.js.map +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +7 -7
- package/dist/index.d.ts +2 -2
- package/dist/index.js +26 -25
- package/dist/index.js.map +1 -1
- package/dist/providers.js +8 -7
- package/dist/rbac/index.d.ts +806 -806
- package/dist/rbac/index.js +937 -1179
- package/dist/rbac/index.js.map +1 -1
- package/dist/{types-DiRQsGJs.d.ts → types-BRDU7N6w.d.ts} +12 -1
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +6 -6
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- 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 +21 -8
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +46 -33
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- 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 +2 -2
- 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 +3 -3
- package/package.json +5 -2
- package/src/__tests__/REBUILD_PLAN.md +223 -0
- package/src/__tests__/TESTING_GUIDELINES.md +341 -0
- package/src/__tests__/fixtures/mocks.ts +93 -0
- package/src/__tests__/helpers/component-test-utils.tsx +145 -0
- package/src/__tests__/helpers/test-utils.tsx +117 -0
- package/src/__tests__/integration/UserProfile.test.tsx +128 -0
- package/src/__tests__/setup.ts +37 -225
- package/src/__tests__/templates/component.test.template.tsx +97 -75
- package/src/__tests__/templates/hook.test.template.ts +173 -0
- package/src/__tests__/types/test.types.ts +106 -0
- package/src/components/Alert/Alert.test.tsx +496 -0
- package/src/components/Avatar/Avatar.test.tsx +484 -0
- package/src/components/Button/Button.test.tsx +662 -0
- package/src/components/Card/Card.test.tsx +593 -0
- package/src/components/Checkbox/Checkbox.test.tsx +461 -0
- package/src/components/DataTable/DataTable.tsx +9 -1
- package/src/components/DataTable/components/AccessDeniedPage.tsx +168 -0
- package/src/components/DataTable/components/ActionButtons.tsx +18 -1
- package/src/components/DataTable/components/DataTableCore.tsx +97 -11
- package/src/components/DataTable/components/DataTableToolbar.tsx +22 -10
- package/src/components/DataTable/components/UnifiedTableBody.tsx +33 -4
- package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -0
- package/src/components/DataTable/examples/HierarchicalExample.tsx +3 -0
- package/src/components/DataTable/examples/InitialPageSizeExample.tsx +3 -0
- package/src/components/DataTable/examples/PerformanceExample.tsx +3 -0
- package/src/components/DataTable/types.ts +39 -1
- package/src/components/Dialog/Dialog.test.tsx +1139 -0
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +752 -0
- package/src/components/FileUpload/FileUpload.test.tsx +665 -0
- package/src/hooks/useCounter.test.ts +135 -0
- package/src/rbac/index.ts +3 -3
- package/dist/chunk-2V3Y6YBC.js.map +0 -1
- package/dist/chunk-BEZRLNK3.js +0 -1744
- package/dist/chunk-BEZRLNK3.js.map +0 -1
- package/dist/chunk-ETEJVKYK.js.map +0 -1
- package/dist/chunk-EWKPTNPO.js.map +0 -1
- package/dist/chunk-OHXGNT3K.js +0 -21
- package/dist/chunk-OHXGNT3K.js.map +0 -1
- package/dist/chunk-RRUYHORU.js.map +0 -1
- package/src/__tests__/README.md +0 -404
- package/src/__tests__/debug-provider.unit.test.tsx +0 -67
- package/src/__tests__/e2e/workflows.test.tsx +0 -373
- package/src/__tests__/hybridPermissions.unit.test.tsx +0 -474
- package/src/__tests__/index.integration.test.ts +0 -491
- package/src/__tests__/mocks/MockAuthProvider-standalone.tsx +0 -47
- package/src/__tests__/mocks/MockAuthProvider.tsx +0 -63
- package/src/__tests__/mocks/enhancedSupabaseMock.ts +0 -252
- package/src/__tests__/mocks/index.test.ts +0 -23
- package/src/__tests__/mocks/index.ts +0 -16
- package/src/__tests__/mocks/mockAuth.ts +0 -155
- package/src/__tests__/mocks/mockSupabase.ts +0 -83
- package/src/__tests__/mocks/mockSupabaseClient.ts +0 -63
- package/src/__tests__/mocks/providers.tsx +0 -22
- package/src/__tests__/patterns/__tests__/testPatterns.test.ts +0 -394
- package/src/__tests__/patterns/testPatterns.ts +0 -124
- package/src/__tests__/performance/componentPerformance.performance.test.ts +0 -27
- package/src/__tests__/performance/index.ts +0 -24
- package/src/__tests__/performance/performanceValidation.performance.test.ts +0 -15
- package/src/__tests__/security/security.unit.test.tsx +0 -7
- package/src/__tests__/security/securityValidation.security.test.tsx +0 -153
- package/src/__tests__/setupTests.d.ts +0 -1
- package/src/__tests__/shared/componentTestUtils.tsx +0 -475
- package/src/__tests__/shared/errorHandlingTestUtils.ts +0 -107
- package/src/__tests__/shared/index.ts +0 -81
- package/src/__tests__/shared/integrationTestUtils.tsx +0 -375
- package/src/__tests__/shared/performanceTestUtils.tsx +0 -476
- package/src/__tests__/shared/testUtils.optimized.tsx +0 -685
- package/src/__tests__/simple.test.tsx +0 -20
- package/src/__tests__/test-utils/dataFactories.ts +0 -60
- package/src/__tests__/test-utils/index.ts +0 -6
- package/src/__tests__/typeSafety.unit.test.ts +0 -65
- package/src/__tests__/unifiedAuth.unit.test.tsx +0 -151
- package/src/__tests__/utils/accessibilityHelpers.ts +0 -254
- package/src/__tests__/utils/assertions.ts +0 -50
- package/src/__tests__/utils/deterministicHelpers.ts +0 -31
- package/src/__tests__/utils/edgeCaseConfig.test.ts +0 -75
- package/src/__tests__/utils/edgeCaseConfig.ts +0 -98
- package/src/__tests__/utils/mockHelpers.ts +0 -149
- package/src/__tests__/utils/mockLoader.ts +0 -101
- package/src/__tests__/utils/performanceHelpers.ts +0 -55
- package/src/__tests__/utils/performanceTestHelpers.ts +0 -68
- package/src/__tests__/utils/testDataFactories.ts +0 -28
- package/src/__tests__/utils/testIsolation.ts +0 -67
- package/src/__tests__/utils/visualTestHelpers.ts +0 -20
- package/src/__tests__/visual/__snapshots__/componentSnapshots.visual.test.tsx.snap +0 -68
- package/src/__tests__/visual/__snapshots__/componentVisuals.visual.test.tsx.snap +0 -14
- package/src/__tests__/visual/__snapshots__/visualRegression.test.tsx.snap +0 -217
- package/src/__tests__/visual/__snapshots__/visualRegression.visual.test.tsx.snap +0 -24
- package/src/__tests__/visual/componentSnapshots.visual.test.tsx +0 -33
- package/src/__tests__/visual/componentVisuals.visual.test.tsx +0 -12
- package/src/__tests__/visual/visualRegression.visual.test.tsx +0 -20
- package/src/components/Alert/__tests__/Alert.unit.test.tsx +0 -381
- package/src/components/Avatar/__tests__/Avatar.unit.test.tsx +0 -232
- package/src/components/Button/__tests__/Button.accessibility.test.tsx +0 -131
- package/src/components/Button/__tests__/Button.comprehensive.test.tsx +0 -721
- package/src/components/Button/__tests__/Button.unit.test.tsx +0 -189
- package/src/components/Button/__tests__/EventSelector.integration.test.tsx +0 -285
- package/src/components/Card/__tests__/Card.accessibility.test.tsx +0 -394
- package/src/components/Card/__tests__/Card.comprehensive.test.tsx +0 -599
- package/src/components/Card/__tests__/Card.integration.test.tsx +0 -673
- package/src/components/Card/__tests__/Card.performance.test.tsx +0 -546
- package/src/components/Card/__tests__/Card.unit.test.tsx +0 -330
- package/src/components/Card/__tests__/Card.visual.test.tsx +0 -599
- package/src/components/Card/__tests__/README.md +0 -211
- package/src/components/Checkbox/__tests__/Checkbox.unit.test.tsx +0 -520
- package/src/components/DataTable/__tests__/DataTable.errorHandling.test.tsx +0 -251
- package/src/components/DataTable/__tests__/DataTable.hierarchical.test.tsx +0 -680
- package/src/components/DataTable/__tests__/DataTable.infinite-loop.test.tsx +0 -323
- package/src/components/DataTable/__tests__/DataTable.integration.test.tsx +0 -716
- package/src/components/DataTable/__tests__/DataTable.performance.test.tsx +0 -589
- package/src/components/DataTable/__tests__/DataTable.permissions.test.tsx +0 -316
- package/src/components/DataTable/__tests__/DataTable.regressionFixes.test.tsx +0 -546
- package/src/components/DataTable/__tests__/DataTable.selection.controlled.test.tsx +0 -386
- package/src/components/DataTable/__tests__/DataTable.selection.test.tsx +0 -338
- package/src/components/DataTable/__tests__/DataTable.sorting.test.tsx +0 -321
- package/src/components/DataTable/__tests__/DataTable.userWorkflows.test.tsx +0 -320
- package/src/components/DataTable/__tests__/DataTable.workflowValidation.test.tsx +0 -583
- package/src/components/DataTable/__tests__/DataTable.workflows.test.tsx +0 -711
- package/src/components/DataTable/__tests__/performance-regression.test.tsx +0 -777
- package/src/components/DataTable/__tests__/performance.test.tsx +0 -365
- package/src/components/DataTable/components/__tests__/ActionButtons.unit.test.tsx +0 -150
- package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +0 -224
- package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.unit.test.tsx +0 -244
- package/src/components/DataTable/components/__tests__/DataTable.accessibility.test.tsx +0 -629
- package/src/components/DataTable/components/__tests__/DataTable.integration.test.tsx +0 -470
- package/src/components/DataTable/components/__tests__/DataTable.performance.test.tsx +0 -160
- package/src/components/DataTable/components/__tests__/DataTable.real.test.tsx +0 -251
- package/src/components/DataTable/components/__tests__/DataTable.security.test.tsx +0 -171
- package/src/components/DataTable/components/__tests__/DataTable.unit.test.tsx +0 -290
- package/src/components/DataTable/components/__tests__/DataTableBody.unit.test.tsx +0 -147
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.unit.test.tsx +0 -182
- package/src/components/DataTable/components/__tests__/DataTableModals.unit.test.tsx +0 -123
- package/src/components/DataTable/components/__tests__/EditableRow.unit.test.tsx +0 -660
- package/src/components/DataTable/components/__tests__/EmptyState.unit.test.tsx +0 -256
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -498
- package/src/components/DataTable/components/__tests__/FilterRow.unit.test.tsx +0 -112
- package/src/components/DataTable/components/__tests__/FilteringToggle.unit.test.tsx +0 -133
- package/src/components/DataTable/components/__tests__/GroupHeader.unit.test.tsx +0 -172
- package/src/components/DataTable/components/__tests__/GroupingDropdown.unit.test.tsx +0 -222
- package/src/components/DataTable/components/__tests__/ImportModal.unit.test.tsx +0 -780
- package/src/components/DataTable/components/__tests__/LoadingState.unit.test.tsx +0 -65
- package/src/components/DataTable/components/__tests__/PaginationControls.unit.test.tsx +0 -634
- package/src/components/DataTable/components/__tests__/StateComponents.unit.test.tsx +0 -48
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.hierarchical.test.tsx +0 -541
- package/src/components/DataTable/components/__tests__/ViewRowModal.unit.test.tsx +0 -228
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.unit.test.tsx +0 -568
- package/src/components/DataTable/core/__tests__/ActionManager.unit.test.ts +0 -405
- package/src/components/DataTable/core/__tests__/ArchitectureIntegration.unit.test.tsx +0 -445
- package/src/components/DataTable/core/__tests__/ColumnFactory.unit.test.ts +0 -288
- package/src/components/DataTable/core/__tests__/ColumnManager.unit.test.ts +0 -623
- package/src/components/DataTable/core/__tests__/DataManager.unit.test.ts +0 -431
- package/src/components/DataTable/core/__tests__/DataTableContext.unit.test.tsx +0 -433
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.unit.test.ts +0 -422
- package/src/components/DataTable/core/__tests__/PluginRegistry.unit.test.tsx +0 -207
- package/src/components/DataTable/core/__tests__/StateManager.unit.test.ts +0 -278
- package/src/components/DataTable/examples/__tests__/PerformanceExample.unit.test.tsx +0 -281
- package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.unit.test.ts +0 -407
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.unit.test.ts +0 -679
- package/src/components/DataTable/utils/__tests__/debugTools.unit.test.ts +0 -267
- package/src/components/DataTable/utils/__tests__/errorHandling.unit.test.ts +0 -467
- package/src/components/DataTable/utils/__tests__/exportUtils.unit.test.ts +0 -380
- package/src/components/DataTable/utils/__tests__/flexibleImport.unit.test.ts +0 -233
- package/src/components/DataTable/utils/__tests__/performanceUtils.unit.test.ts +0 -414
- package/src/components/Dialog/__tests__/Dialog.accessibility.test.tsx +0 -521
- package/src/components/Dialog/__tests__/Dialog.auto-size.example.tsx +0 -157
- package/src/components/Dialog/__tests__/Dialog.enhanced.test.tsx +0 -538
- package/src/components/Dialog/__tests__/Dialog.unit.test.tsx +0 -1373
- package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +0 -151
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +0 -611
- package/src/components/ErrorBoundary/__tests__/ErrorBoundary.accessibility.test.tsx +0 -517
- package/src/components/ErrorBoundary/__tests__/ErrorBoundary.integration.test.tsx +0 -572
- package/src/components/ErrorBoundary/__tests__/ErrorBoundary.unit.test.tsx +0 -579
- package/src/components/EventSelector/__tests__/EventSelector.test.tsx +0 -528
- package/src/components/FileUpload/__tests__/FileUpload.integration.test.tsx +0 -992
- package/src/components/FileUpload/__tests__/FileUpload.real.test.tsx +0 -927
- package/src/components/FileUpload/__tests__/FileUpload.test.tsx +0 -855
- package/src/components/FileUpload/__tests__/FileUpload.unit.test.tsx +0 -1311
- package/src/components/FileUpload/__tests__/FileUpload.unmocked.test.tsx +0 -937
- package/src/components/Footer/__tests__/Footer.accessibility.test.tsx +0 -359
- package/src/components/Footer/__tests__/Footer.integration.test.tsx +0 -353
- package/src/components/Footer/__tests__/Footer.performance.test.tsx +0 -309
- package/src/components/Footer/__tests__/Footer.unit.test.tsx +0 -309
- package/src/components/Footer/__tests__/Footer.visual.test.tsx +0 -335
- package/src/components/Form/__tests__/Form.accessibility.test.tsx +0 -820
- package/src/components/Form/__tests__/Form.unit.test.tsx +0 -305
- package/src/components/Form/__tests__/FormErrorSummary.unit.test.tsx +0 -285
- package/src/components/Form/__tests__/FormFieldset.unit.test.tsx +0 -241
- package/src/components/Header/__tests__/Header.accessibility.test.tsx +0 -382
- package/src/components/Header/__tests__/Header.comprehensive.test.tsx +0 -509
- package/src/components/Header/__tests__/Header.unit.test.tsx +0 -335
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +0 -196
- package/src/components/InactivityWarningModal/__tests__/InactivityWarningModal.unit.test.tsx +0 -224
- package/src/components/Input/__tests__/Input.accessibility.test.tsx +0 -632
- package/src/components/Input/__tests__/Input.unit.test.tsx +0 -1121
- package/src/components/Label/__tests__/Label.accessibility.test.tsx +0 -239
- package/src/components/Label/__tests__/Label.unit.test.tsx +0 -331
- package/src/components/LoadingSpinner/__tests__/LoadingSpinner.accessibility.test.tsx +0 -116
- package/src/components/LoadingSpinner/__tests__/LoadingSpinner.unit.test.tsx +0 -144
- package/src/components/LoginForm/__tests__/LoginForm.accessibility.test.tsx +0 -201
- package/src/components/LoginForm/__tests__/LoginForm.unit.test.tsx +0 -119
- package/src/components/NavigationMenu/__tests__/NavigationMenu.accessibility.test.tsx +0 -378
- package/src/components/NavigationMenu/__tests__/NavigationMenu.enhanced.test.tsx +0 -768
- package/src/components/NavigationMenu/__tests__/NavigationMenu.integration.test.tsx +0 -576
- package/src/components/NavigationMenu/__tests__/NavigationMenu.performance.test.tsx +0 -585
- package/src/components/NavigationMenu/__tests__/NavigationMenu.real.component.test.tsx +0 -783
- package/src/components/NavigationMenu/__tests__/NavigationMenu.security.enhanced.test.tsx +0 -810
- package/src/components/NavigationMenu/__tests__/NavigationMenu.security.test.tsx +0 -494
- package/src/components/NavigationMenu/__tests__/NavigationMenu.unit.test.tsx +0 -331
- package/src/components/NavigationMenu/__tests__/NavigationMenu.userWorkflows.test.tsx +0 -347
- package/src/components/NavigationMenu/__tests__/NavigationMenu.workflows.test.tsx +0 -584
- package/src/components/OrganisationSelector/__tests__/OrganisationSelector.unit.test.tsx +0 -664
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +0 -288
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -893
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +0 -629
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -782
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -904
- package/src/components/PaceLoginPage/__tests__/PaceLoginPage.accessibility.test.tsx +0 -463
- package/src/components/PaceLoginPage/__tests__/PaceLoginPage.integration.test.tsx +0 -586
- package/src/components/PaceLoginPage/__tests__/PaceLoginPage.unit.test.tsx +0 -533
- package/src/components/PasswordReset/__tests__/PasswordChangeForm.accessibility.test.tsx +0 -408
- package/src/components/PasswordReset/__tests__/PasswordChangeForm.unit.test.tsx +0 -561
- package/src/components/PasswordReset/__tests__/PasswordReset.integration.test.tsx +0 -304
- package/src/components/PasswordReset/__tests__/PasswordResetForm.accessibility.test.tsx +0 -20
- package/src/components/PasswordReset/__tests__/PasswordResetForm.unit.test.tsx +0 -523
- package/src/components/PasswordReset/__tests__/__mocks__/UnifiedAuthProvider.ts +0 -29
- package/src/components/Print/__tests__/Print.comprehensive.test.tsx +0 -331
- package/src/components/PrintButton/__tests__/PrintButton.unit.test.tsx +0 -429
- package/src/components/PrintButton/__tests__/PrintButtonGroup.unit.test.tsx +0 -277
- package/src/components/PrintButton/__tests__/PrintToolbar.unit.test.tsx +0 -264
- package/src/components/PrintCard/__tests__/PrintCard.unit.test.tsx +0 -233
- package/src/components/PrintCard/__tests__/PrintCardContent.test.tsx +0 -284
- package/src/components/PrintCard/__tests__/PrintCardGrid.unit.test.tsx +0 -214
- package/src/components/PrintCard/__tests__/PrintCardImage.unit.test.tsx +0 -264
- package/src/components/PrintDataTable/__tests__/PrintDataTable.unit.test.tsx +0 -361
- package/src/components/PrintDataTable/__tests__/PrintTableGroup.unit.test.tsx +0 -314
- package/src/components/PrintDataTable/__tests__/PrintTableRow.unit.test.tsx +0 -362
- package/src/components/PrintFooter/__tests__/PrintFooter.unit.test.tsx +0 -500
- package/src/components/PrintFooter/__tests__/PrintFooterContent.unit.test.tsx +0 -321
- package/src/components/PrintFooter/__tests__/PrintFooterInfo.unit.test.tsx +0 -335
- package/src/components/PrintFooter/__tests__/PrintPageNumber.unit.test.tsx +0 -340
- package/src/components/PrintGrid/__tests__/PrintGrid.unit.test.tsx +0 -340
- package/src/components/PrintGrid/__tests__/PrintGridBreakpoint.unit.test.tsx +0 -261
- package/src/components/PrintGrid/__tests__/PrintGridContainer.unit.test.tsx +0 -338
- package/src/components/PrintGrid/__tests__/PrintGridItem.unit.test.tsx +0 -338
- package/src/components/PrintHeader/__tests__/PrintCoverHeader.unit.test.tsx +0 -309
- package/src/components/PrintHeader/__tests__/PrintHeader.unit.test.tsx +0 -202
- package/src/components/PrintLayout/__tests__/PrintLayout.unit.test.tsx +0 -238
- package/src/components/PrintPageBreak/__tests__/PrintPageBreak.unit.test.tsx +0 -263
- package/src/components/PrintPageBreak/__tests__/PrintPageBreakGroup.unit.test.tsx +0 -239
- package/src/components/PrintPageBreak/__tests__/PrintPageBreakIndicator.unit.test.tsx +0 -235
- package/src/components/PrintSection/__tests__/PrintColumn.unit.test.tsx +0 -385
- package/src/components/PrintSection/__tests__/PrintDivider.unit.test.tsx +0 -373
- package/src/components/PrintSection/__tests__/PrintSection.unit.test.tsx +0 -390
- package/src/components/PrintSection/__tests__/PrintSectionContent.unit.test.tsx +0 -321
- package/src/components/PrintSection/__tests__/PrintSectionHeader.unit.test.tsx +0 -334
- package/src/components/PrintText/__tests__/PrintText.unit.test.tsx +0 -351
- package/src/components/Progress/__tests__/Progress.accessibility.test.tsx +0 -240
- package/src/components/Progress/__tests__/Progress.unit.test.tsx +0 -242
- package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +0 -761
- package/src/components/PublicLayout/__tests__/PublicErrorBoundary.simplified.test.tsx +0 -228
- package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +0 -228
- package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +0 -459
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +0 -362
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +0 -522
- package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +0 -599
- package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +0 -513
- package/src/components/RBAC/__tests__/PagePermissionGuard.unit.test.tsx +0 -683
- package/src/components/RBAC/__tests__/RBAC.integration.test.tsx +0 -573
- package/src/components/RBAC/__tests__/RBACGuard.unit.test.tsx +0 -467
- package/src/components/RBAC/__tests__/RBACProvider.accessibility.test.tsx +0 -475
- package/src/components/RBAC/__tests__/RBACProvider.advanced.test.tsx +0 -569
- package/src/components/RBAC/__tests__/RBACProvider.integration.test.tsx +0 -352
- package/src/components/RBAC/__tests__/RBACProvider.unit.test.tsx +0 -128
- package/src/components/RBAC/__tests__/RoleBasedContent.unit.test.tsx +0 -657
- package/src/components/Select/__tests__/SearchableSelect.unit.test.tsx +0 -437
- package/src/components/Select/__tests__/Select.accessibility.test.tsx +0 -1202
- package/src/components/Select/__tests__/Select.actual.test.tsx +0 -774
- package/src/components/Select/__tests__/Select.comprehensive.test.tsx +0 -837
- package/src/components/Select/__tests__/Select.enhanced.test.tsx +0 -1101
- package/src/components/Select/__tests__/Select.integration.test.tsx +0 -772
- package/src/components/Select/__tests__/Select.performance.test.tsx +0 -695
- package/src/components/Select/__tests__/Select.real-world.test.tsx +0 -1046
- package/src/components/Select/__tests__/Select.search-algorithms.test.tsx +0 -968
- package/src/components/Select/__tests__/Select.unit.test.tsx +0 -647
- package/src/components/Select/__tests__/Select.utils.test.tsx +0 -890
- package/src/components/Table/__tests__/Table.accessibility.test.tsx +0 -233
- package/src/components/Table/__tests__/Table.unit.test.tsx +0 -235
- package/src/components/Toast/__tests__/Toast.accessibility.test.tsx +0 -238
- package/src/components/Toast/__tests__/Toast.integration.test.tsx +0 -699
- package/src/components/Toast/__tests__/Toast.unit.test.tsx +0 -750
- package/src/components/Tooltip/__tests__/Tooltip.accessibility.test.tsx +0 -121
- package/src/components/Tooltip/__tests__/Tooltip.unit.test.tsx +0 -185
- package/src/components/UserMenu/__tests__/UserMenu.accessibility.test.tsx +0 -139
- package/src/components/UserMenu/__tests__/UserMenu.integration.test.tsx +0 -188
- package/src/components/UserMenu/__tests__/UserMenu.unit.test.tsx +0 -458
- package/src/components/__tests__/EdgeCaseTesting.enhanced.test.tsx +0 -524
- package/src/components/__tests__/ErrorTesting.enhanced.test.tsx +0 -455
- package/src/components/__tests__/SuperAdminGuard.test.tsx +0 -456
- package/src/components/__tests__/SuperAdminGuard.unit.test.tsx +0 -456
- package/src/components/examples/__tests__/PermissionExample.unit.test.tsx +0 -360
- package/src/hooks/__tests__/hooks.integration.test.tsx +0 -575
- package/src/hooks/__tests__/useApiFetch.unit.test.ts +0 -115
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +0 -133
- package/src/hooks/__tests__/useDebounce.unit.test.ts +0 -82
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +0 -293
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +0 -385
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -286
- package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +0 -838
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -627
- package/src/hooks/__tests__/useRBAC.unit.test.ts +0 -911
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -537
- package/src/hooks/__tests__/useToast.unit.test.tsx +0 -62
- package/src/hooks/__tests__/useZodForm.unit.test.tsx +0 -37
- package/src/hooks/public/__tests__/usePublicEvent.test.tsx +0 -397
- package/src/hooks/public/__tests__/usePublicEventLogo.test.tsx +0 -690
- package/src/hooks/public/__tests__/usePublicRouteParams.test.tsx +0 -449
- package/src/providers/__tests__/EventProvider.unit.test.tsx +0 -768
- package/src/providers/__tests__/OrganisationProvider.basic.test.tsx +0 -116
- package/src/providers/__tests__/OrganisationProvider.unit.test.tsx +0 -1312
- package/src/providers/__tests__/UnifiedAuthProvider.inactivity.test.tsx +0 -601
- package/src/providers/__tests__/UnifiedAuthProvider.unit.test.tsx +0 -683
- package/src/providers/__tests__/index.unit.test.ts +0 -78
- package/src/rbac/__tests__/PagePermissionGuard.test.tsx +0 -673
- package/src/rbac/__tests__/README.md +0 -170
- package/src/rbac/__tests__/RoleBasedRouter.test.tsx +0 -709
- package/src/rbac/__tests__/TestContext.tsx +0 -72
- package/src/rbac/__tests__/__mocks__/cache.ts +0 -144
- package/src/rbac/__tests__/__mocks__/supabase.ts +0 -152
- package/src/rbac/__tests__/adapters-hooks-comprehensive.test.tsx +0 -782
- package/src/rbac/__tests__/adapters-hooks.test.tsx +0 -561
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +0 -963
- package/src/rbac/__tests__/adapters.test.tsx +0 -444
- package/src/rbac/__tests__/api.test.ts +0 -620
- package/src/rbac/__tests__/audit-observability-comprehensive.test.ts +0 -792
- package/src/rbac/__tests__/audit-observability.test.ts +0 -549
- package/src/rbac/__tests__/audit.test.ts +0 -616
- package/src/rbac/__tests__/build-contract-compliance-simple.test.ts +0 -230
- package/src/rbac/__tests__/cache-invalidation-comprehensive.test.ts +0 -889
- package/src/rbac/__tests__/cache-invalidation.test.ts +0 -457
- package/src/rbac/__tests__/cache.test.ts +0 -458
- package/src/rbac/__tests__/components-navigation-guard.enhanced.test.tsx +0 -859
- package/src/rbac/__tests__/components-navigation-guard.test.tsx +0 -895
- package/src/rbac/__tests__/components-navigation-provider.test.tsx +0 -692
- package/src/rbac/__tests__/components-page-permission-guard.test.tsx +0 -673
- package/src/rbac/__tests__/components-page-permission-provider.test.tsx +0 -614
- package/src/rbac/__tests__/components-permission-enforcer.enhanced.fixed.test.tsx +0 -836
- package/src/rbac/__tests__/components-permission-enforcer.enhanced.test.tsx +0 -837
- package/src/rbac/__tests__/components-permission-enforcer.test.tsx +0 -825
- package/src/rbac/__tests__/components-role-based-router.test.tsx +0 -709
- package/src/rbac/__tests__/components-secure-data-provider.test.tsx +0 -607
- package/src/rbac/__tests__/config.test.ts +0 -583
- package/src/rbac/__tests__/core-logic-unit.test.ts +0 -190
- package/src/rbac/__tests__/core-permission-logic-comprehensive.test.ts +0 -1467
- package/src/rbac/__tests__/core-permission-logic-fixed.test.ts +0 -151
- package/src/rbac/__tests__/core-permission-logic-simple.test.ts +0 -968
- package/src/rbac/__tests__/core-permission-logic.test.ts +0 -966
- package/src/rbac/__tests__/edge-cases-comprehensive.test.ts +0 -988
- package/src/rbac/__tests__/edge-cases.test.ts +0 -654
- package/src/rbac/__tests__/engine.test.ts +0 -361
- package/src/rbac/__tests__/engine.unit.test.ts +0 -361
- package/src/rbac/__tests__/hooks.enhanced.test.tsx +0 -979
- package/src/rbac/__tests__/hooks.fixed.test.tsx +0 -475
- package/src/rbac/__tests__/hooks.test.tsx +0 -385
- package/src/rbac/__tests__/index.test.ts +0 -269
- package/src/rbac/__tests__/integration.enhanced.test.tsx +0 -824
- package/src/rbac/__tests__/page-permission-guard-super-admin.test.tsx +0 -261
- package/src/rbac/__tests__/performance.enhanced.test.tsx +0 -724
- package/src/rbac/__tests__/permissions.test.ts +0 -383
- package/src/rbac/__tests__/requires-event.test.ts +0 -330
- package/src/rbac/__tests__/scope-isolation-comprehensive.test.ts +0 -1349
- package/src/rbac/__tests__/scope-isolation.test.ts +0 -755
- package/src/rbac/__tests__/secure-client-rls-comprehensive.test.ts +0 -592
- package/src/rbac/__tests__/secure-client-rls.test.ts +0 -377
- package/src/rbac/__tests__/security.test.ts +0 -296
- package/src/rbac/__tests__/setup.ts +0 -228
- package/src/rbac/__tests__/test-utils-enhanced.tsx +0 -400
- package/src/rbac/__tests__/types.test.ts +0 -685
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -631
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -667
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -647
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -496
- package/src/rbac/testing/__tests__/index.test.tsx +0 -342
- package/src/rbac/utils/__tests__/eventContext.test.ts +0 -428
- package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -428
- package/src/styles/__tests__/styles.unit.test.ts +0 -164
- package/src/test-dom-cleanup.test.tsx +0 -38
- package/src/theming/__tests__/README.md +0 -335
- package/src/theming/__tests__/runtime.accessibility.test.ts +0 -474
- package/src/theming/__tests__/runtime.error.test.ts +0 -616
- package/src/theming/__tests__/runtime.integration.test.ts +0 -376
- package/src/theming/__tests__/runtime.performance.test.ts +0 -411
- package/src/theming/__tests__/runtime.unit.test.ts +0 -470
- package/src/types/__tests__/database.unit.test.ts +0 -489
- package/src/types/__tests__/guards.unit.test.ts +0 -146
- package/src/types/__tests__/index.unit.test.ts +0 -77
- package/src/types/__tests__/organisation.unit.test.ts +0 -713
- package/src/types/__tests__/rbac.unit.test.ts +0 -621
- package/src/types/__tests__/security.unit.test.ts +0 -347
- package/src/types/__tests__/supabase.unit.test.ts +0 -658
- package/src/types/__tests__/theme.unit.test.ts +0 -218
- package/src/types/__tests__/unified.unit.test.ts +0 -537
- package/src/types/__tests__/validation.unit.test.ts +0 -616
- package/src/utils/__tests__/appConfig.unit.test.ts +0 -55
- package/src/utils/__tests__/appNameResolver.unit.test.ts +0 -137
- package/src/utils/__tests__/audit.unit.test.ts +0 -69
- package/src/utils/__tests__/auth-utils.unit.test.ts +0 -70
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +0 -317
- package/src/utils/__tests__/cn.unit.test.ts +0 -34
- package/src/utils/__tests__/deviceFingerprint.unit.test.ts +0 -480
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +0 -322
- package/src/utils/__tests__/formatDate.unit.test.ts +0 -109
- package/src/utils/__tests__/formatting.unit.test.ts +0 -66
- package/src/utils/__tests__/index.unit.test.ts +0 -251
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -304
- package/src/utils/__tests__/organisationContext.unit.test.ts +0 -192
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +0 -259
- package/src/utils/__tests__/permissionTypes.unit.test.ts +0 -250
- package/src/utils/__tests__/permissionUtils.unit.test.ts +0 -362
- package/src/utils/__tests__/sanitization.unit.test.ts +0 -346
- package/src/utils/__tests__/schemaUtils.unit.test.ts +0 -441
- package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -334
- package/src/utils/__tests__/secureErrors.unit.test.ts +0 -377
- package/src/utils/__tests__/secureStorage.unit.test.ts +0 -293
- package/src/utils/__tests__/security.unit.test.ts +0 -127
- package/src/utils/__tests__/securityMonitor.unit.test.ts +0 -280
- package/src/utils/__tests__/sessionTracking.unit.test.ts +0 -370
- package/src/utils/__tests__/validation.unit.test.ts +0 -84
- package/src/utils/__tests__/validationUtils.unit.test.ts +0 -571
- package/src/utils/print/__tests__/PrintDataProcessor.unit.test.ts +0 -219
- package/src/utils/print/__tests__/usePrintOptimization.unit.test.tsx +0 -353
- package/src/utils/storage/__tests__/config.unit.test.ts +0 -206
- package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -648
- package/src/utils/storage/__tests__/index.unit.test.ts +0 -167
- package/src/utils/storage/__tests__/types.unit.test.ts +0 -441
- package/src/validation/__tests__/common.unit.test.ts +0 -101
- package/src/validation/__tests__/csrf.unit.test.ts +0 -302
- package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -98
- package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -466
- /package/dist/{DataTable-EEUDXPE5.js.map → DataTable-GX3XERFJ.js.map} +0 -0
- /package/dist/{chunk-VYG4AXYW.js.map → chunk-5EL3KHOQ.js.map} +0 -0
|
@@ -1,968 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Select Component Search Algorithm Tests
|
|
3
|
-
* @package @jmruthers/pace-core
|
|
4
|
-
* @module Components/Select/Select.search-algorithms
|
|
5
|
-
* @since 0.1.0
|
|
6
|
-
*
|
|
7
|
-
* Specialized tests for search algorithms and utility functions used in the Select component.
|
|
8
|
-
* This file focuses on testing the core search functionality, fuzzy matching, text highlighting,
|
|
9
|
-
* and option parsing logic in isolation.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { errorTestingUtils, TestErrorBoundary } from '../../__tests__/ErrorTesting.enhanced.test';
|
|
13
|
-
import React from 'react';
|
|
14
|
-
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
|
|
15
|
-
import userEvent from '@testing-library/user-event';
|
|
16
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
17
|
-
import '@testing-library/jest-dom';
|
|
18
|
-
import { renderWithProviders } from "../../../__tests__/shared";
|
|
19
|
-
import {
|
|
20
|
-
Select,
|
|
21
|
-
SelectContent,
|
|
22
|
-
SelectItem,
|
|
23
|
-
SelectTrigger,
|
|
24
|
-
SelectValue,
|
|
25
|
-
} from '../Select';
|
|
26
|
-
|
|
27
|
-
// Mock lucide-react icons
|
|
28
|
-
vi.mock('lucide-react', () => ({
|
|
29
|
-
Search: () => <div data-testid="search-icon">🔍</div>,
|
|
30
|
-
X: () => <div data-testid="clear-icon">✕</div>,
|
|
31
|
-
ChevronDown: () => <div data-testid="chevron-down-icon">▼</div>,
|
|
32
|
-
Check: () => <div data-testid="check-icon">✓</div>,
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
// Mock Radix UI Select with enhanced search simulation
|
|
36
|
-
vi.mock('@radix-ui/react-select', async () => {
|
|
37
|
-
const actual = await vi.importActual('@radix-ui/react-select');
|
|
38
|
-
return {
|
|
39
|
-
...actual,
|
|
40
|
-
Root: ({ children, onValueChange, value, defaultValue, ...props }: any) => (
|
|
41
|
-
<div data-testid="select-root" data-value={value || defaultValue} {...props}>
|
|
42
|
-
{children}
|
|
43
|
-
</div>
|
|
44
|
-
),
|
|
45
|
-
Trigger: React.forwardRef(({ children, disabled, ...props }: any, ref) => (
|
|
46
|
-
<button
|
|
47
|
-
ref={ref}
|
|
48
|
-
data-testid="select-trigger"
|
|
49
|
-
disabled={disabled}
|
|
50
|
-
onClick={() => {
|
|
51
|
-
// Simulate opening the dropdown
|
|
52
|
-
const event = new CustomEvent('select-open');
|
|
53
|
-
document.dispatchEvent(event);
|
|
54
|
-
}}
|
|
55
|
-
{...props}
|
|
56
|
-
>
|
|
57
|
-
{children}
|
|
58
|
-
</button>
|
|
59
|
-
)),
|
|
60
|
-
Content: ({ children, searchable, searchStrategy, caseSensitive, ...props }: any) => {
|
|
61
|
-
const [searchValue, setSearchValue] = React.useState('');
|
|
62
|
-
const [filteredChildren, setFilteredChildren] = React.useState(children);
|
|
63
|
-
|
|
64
|
-
React.useEffect(() => {
|
|
65
|
-
if (!searchable || !searchValue) {
|
|
66
|
-
setFilteredChildren(children);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Simulate search filtering based on strategy
|
|
71
|
-
const filterOptions = (children: React.ReactNode, searchTerm: string) => {
|
|
72
|
-
const options: React.ReactElement[] = [];
|
|
73
|
-
|
|
74
|
-
React.Children.forEach(children, (child) => {
|
|
75
|
-
if (React.isValidElement(child) && child.type === SelectItem) {
|
|
76
|
-
const text = child.props.children?.toString() || '';
|
|
77
|
-
const value = child.props.value || '';
|
|
78
|
-
|
|
79
|
-
let matches = false;
|
|
80
|
-
const normalizedSearch = caseSensitive ? searchTerm : searchTerm.toLowerCase();
|
|
81
|
-
const normalizedText = caseSensitive ? text : text.toLowerCase();
|
|
82
|
-
const normalizedValue = caseSensitive ? value : value.toLowerCase();
|
|
83
|
-
|
|
84
|
-
switch (searchStrategy) {
|
|
85
|
-
case 'contains':
|
|
86
|
-
matches = normalizedText.includes(normalizedSearch) ||
|
|
87
|
-
normalizedValue.includes(normalizedSearch);
|
|
88
|
-
break;
|
|
89
|
-
case 'startsWith':
|
|
90
|
-
matches = normalizedText.startsWith(normalizedSearch) ||
|
|
91
|
-
normalizedValue.startsWith(normalizedSearch);
|
|
92
|
-
break;
|
|
93
|
-
case 'exact':
|
|
94
|
-
matches = normalizedText === normalizedSearch ||
|
|
95
|
-
normalizedValue === normalizedSearch;
|
|
96
|
-
break;
|
|
97
|
-
case 'fuzzy':
|
|
98
|
-
// Simple fuzzy matching simulation
|
|
99
|
-
matches = fuzzyMatch(text, searchTerm) || fuzzyMatch(value, searchTerm);
|
|
100
|
-
break;
|
|
101
|
-
default:
|
|
102
|
-
matches = normalizedText.includes(normalizedSearch) ||
|
|
103
|
-
normalizedValue.includes(normalizedSearch);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (matches) {
|
|
107
|
-
options.push(child);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
return options;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const filtered = filterOptions(children, searchValue);
|
|
116
|
-
setFilteredChildren(filtered);
|
|
117
|
-
}, [children, searchValue, searchable, searchStrategy, caseSensitive]);
|
|
118
|
-
|
|
119
|
-
return (
|
|
120
|
-
<div data-testid="select-content" data-searchable={searchable} {...props}>
|
|
121
|
-
{searchable && (
|
|
122
|
-
<div data-testid="search-container">
|
|
123
|
-
<div data-testid="search-icon">🔍</div>
|
|
124
|
-
<input
|
|
125
|
-
data-testid="select-search-input"
|
|
126
|
-
type="text"
|
|
127
|
-
placeholder="Search..."
|
|
128
|
-
aria-label="Search options"
|
|
129
|
-
value={searchValue}
|
|
130
|
-
onChange={(e) => setSearchValue(e.target.value)}
|
|
131
|
-
/>
|
|
132
|
-
{searchValue && (
|
|
133
|
-
<button
|
|
134
|
-
data-testid="select-clear-search"
|
|
135
|
-
aria-label="Clear search"
|
|
136
|
-
type="button"
|
|
137
|
-
onClick={() => setSearchValue('')}
|
|
138
|
-
>
|
|
139
|
-
✕
|
|
140
|
-
</button>
|
|
141
|
-
)}
|
|
142
|
-
</div>
|
|
143
|
-
)}
|
|
144
|
-
<div data-testid="select-viewport">
|
|
145
|
-
{filteredChildren}
|
|
146
|
-
</div>
|
|
147
|
-
</div>
|
|
148
|
-
);
|
|
149
|
-
},
|
|
150
|
-
Viewport: ({ children, ...props }: any) => (
|
|
151
|
-
<div data-testid="select-viewport" {...props}>
|
|
152
|
-
{children}
|
|
153
|
-
</div>
|
|
154
|
-
),
|
|
155
|
-
Item: ({ children, value, disabled, ...props }: any) => (
|
|
156
|
-
<div
|
|
157
|
-
data-testid="select-item"
|
|
158
|
-
role="option"
|
|
159
|
-
data-value={value}
|
|
160
|
-
aria-disabled={disabled}
|
|
161
|
-
onClick={() => {
|
|
162
|
-
if (!disabled) {
|
|
163
|
-
// Simulate value change
|
|
164
|
-
const event = new CustomEvent('select-value-change', { detail: value });
|
|
165
|
-
document.dispatchEvent(event);
|
|
166
|
-
}
|
|
167
|
-
}}
|
|
168
|
-
{...props}
|
|
169
|
-
>
|
|
170
|
-
{children}
|
|
171
|
-
</div>
|
|
172
|
-
),
|
|
173
|
-
ItemText: ({ children, ...props }: any) => (
|
|
174
|
-
<span data-testid="select-item-text" {...props}>
|
|
175
|
-
{children}
|
|
176
|
-
</span>
|
|
177
|
-
),
|
|
178
|
-
ItemIndicator: ({ children, ...props }: any) => (
|
|
179
|
-
<span data-testid="select-item-indicator" {...props}>
|
|
180
|
-
{children}
|
|
181
|
-
</span>
|
|
182
|
-
),
|
|
183
|
-
Value: ({ children, placeholder, ...props }: any) => (
|
|
184
|
-
<span data-testid="select-value" data-placeholder={placeholder} {...props}>
|
|
185
|
-
{children || placeholder}
|
|
186
|
-
</span>
|
|
187
|
-
),
|
|
188
|
-
Label: ({ children, ...props }: any) => (
|
|
189
|
-
<div data-testid="select-label" {...props}>
|
|
190
|
-
{children}
|
|
191
|
-
</div>
|
|
192
|
-
),
|
|
193
|
-
Group: ({ children, ...props }: any) => (
|
|
194
|
-
<div data-testid="select-group" {...props}>
|
|
195
|
-
{children}
|
|
196
|
-
</div>
|
|
197
|
-
),
|
|
198
|
-
Separator: ({ ...props }: any) => (
|
|
199
|
-
<div data-testid="select-separator" {...props} />
|
|
200
|
-
),
|
|
201
|
-
Icon: ({ children, ...props }: any) => (
|
|
202
|
-
<span data-testid="select-icon" {...props}>
|
|
203
|
-
{children}
|
|
204
|
-
</span>
|
|
205
|
-
),
|
|
206
|
-
Portal: ({ children }: any) => <>{children}</>,
|
|
207
|
-
};
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
// Fuzzy match function for testing
|
|
211
|
-
const fuzzyMatch = (text: string, pattern: string): boolean => {
|
|
212
|
-
const textLower = text.toLowerCase();
|
|
213
|
-
const patternLower = pattern.toLowerCase();
|
|
214
|
-
|
|
215
|
-
let textIndex = 0;
|
|
216
|
-
let patternIndex = 0;
|
|
217
|
-
|
|
218
|
-
while (textIndex < textLower.length && patternIndex < patternLower.length) {
|
|
219
|
-
if (textLower[textIndex] === patternLower[patternIndex]) {
|
|
220
|
-
patternIndex++;
|
|
221
|
-
}
|
|
222
|
-
textIndex++;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return patternIndex === patternLower.length;
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
describe('Select Search Algorithms', () => {
|
|
229
|
-
const user = userEvent.setup();
|
|
230
|
-
|
|
231
|
-
beforeEach(() => {
|
|
232
|
-
vi.clearAllMocks();
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
describe('Contains Search Strategy', () => {
|
|
236
|
-
it('finds options containing search term anywhere in text', async () => {
|
|
237
|
-
renderWithProviders(
|
|
238
|
-
<Select>
|
|
239
|
-
<SelectTrigger>
|
|
240
|
-
<SelectValue placeholder="Select an option" />
|
|
241
|
-
</SelectTrigger>
|
|
242
|
-
<SelectContent searchable searchStrategy="contains">
|
|
243
|
-
<SelectItem value="javascript">JavaScript Programming</SelectItem>
|
|
244
|
-
<SelectItem value="typescript">TypeScript Programming</SelectItem>
|
|
245
|
-
<SelectItem value="python">Python Programming</SelectItem>
|
|
246
|
-
<SelectItem value="java">Java Programming</SelectItem>
|
|
247
|
-
</SelectContent>
|
|
248
|
-
</Select>
|
|
249
|
-
);
|
|
250
|
-
|
|
251
|
-
// Click trigger to open the select
|
|
252
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
253
|
-
await user.click(trigger1);
|
|
254
|
-
|
|
255
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
256
|
-
|
|
257
|
-
// Search for "script" - should find JavaScript and TypeScript
|
|
258
|
-
fireEvent.change(searchInput, { target: { value: 'script' } });
|
|
259
|
-
expect(searchInput).toHaveValue('script');
|
|
260
|
-
|
|
261
|
-
// Should find items containing "script"
|
|
262
|
-
const items = screen.getAllByTestId('select-item');
|
|
263
|
-
expect(items.length).toBeGreaterThan(0);
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
it('handles case-insensitive contains search', async () => {
|
|
267
|
-
renderWithProviders(
|
|
268
|
-
<Select>
|
|
269
|
-
<SelectTrigger>
|
|
270
|
-
<SelectValue placeholder="Select an option" />
|
|
271
|
-
</SelectTrigger>
|
|
272
|
-
<SelectContent searchable searchStrategy="contains" caseSensitive={false}>
|
|
273
|
-
<SelectItem value="react">React Framework</SelectItem>
|
|
274
|
-
<SelectItem value="vue">Vue Framework</SelectItem>
|
|
275
|
-
<SelectItem value="angular">Angular Framework</SelectItem>
|
|
276
|
-
</SelectContent>
|
|
277
|
-
</Select>
|
|
278
|
-
);
|
|
279
|
-
|
|
280
|
-
// Click trigger to open the select
|
|
281
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
282
|
-
await user.click(trigger1);
|
|
283
|
-
|
|
284
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
285
|
-
|
|
286
|
-
// Case-insensitive search
|
|
287
|
-
fireEvent.change(searchInput, { target: { value: 'react' } });
|
|
288
|
-
expect(searchInput).toHaveValue('react');
|
|
289
|
-
|
|
290
|
-
await user.clear(searchInput, { delay: 0 });
|
|
291
|
-
fireEvent.change(searchInput, { target: { value: 'REACT' } });
|
|
292
|
-
expect(searchInput).toHaveValue('REACT');
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
it('handles case-sensitive contains search', async () => {
|
|
296
|
-
renderWithProviders(
|
|
297
|
-
<Select>
|
|
298
|
-
<SelectTrigger>
|
|
299
|
-
<SelectValue placeholder="Select an option" />
|
|
300
|
-
</SelectTrigger>
|
|
301
|
-
<SelectContent searchable searchStrategy="contains" caseSensitive>
|
|
302
|
-
<SelectItem value="React">React Framework</SelectItem>
|
|
303
|
-
<SelectItem value="react">react framework</SelectItem>
|
|
304
|
-
<SelectItem value="REACT">REACT FRAMEWORK</SelectItem>
|
|
305
|
-
</SelectContent>
|
|
306
|
-
</Select>
|
|
307
|
-
);
|
|
308
|
-
|
|
309
|
-
// Click trigger to open the select
|
|
310
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
311
|
-
await user.click(trigger1);
|
|
312
|
-
|
|
313
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
314
|
-
|
|
315
|
-
// Case-sensitive search
|
|
316
|
-
fireEvent.change(searchInput, { target: { value: 'React' } });
|
|
317
|
-
expect(searchInput).toHaveValue('React');
|
|
318
|
-
|
|
319
|
-
await user.clear(searchInput, { delay: 0 });
|
|
320
|
-
fireEvent.change(searchInput, { target: { value: 'react' } });
|
|
321
|
-
expect(searchInput).toHaveValue('react');
|
|
322
|
-
});
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
describe('StartsWith Search Strategy', () => {
|
|
326
|
-
it('finds options starting with search term', async () => {
|
|
327
|
-
renderWithProviders(
|
|
328
|
-
<Select>
|
|
329
|
-
<SelectTrigger>
|
|
330
|
-
<SelectValue placeholder="Select an option" />
|
|
331
|
-
</SelectTrigger>
|
|
332
|
-
<SelectContent searchable searchStrategy="startsWith">
|
|
333
|
-
<SelectItem value="react">React Framework</SelectItem>
|
|
334
|
-
<SelectItem value="react-native">React Native</SelectItem>
|
|
335
|
-
<SelectItem value="react-query">React Query</SelectItem>
|
|
336
|
-
<SelectItem value="vue">Vue Framework</SelectItem>
|
|
337
|
-
</SelectContent>
|
|
338
|
-
</Select>
|
|
339
|
-
);
|
|
340
|
-
|
|
341
|
-
// Click trigger to open the select
|
|
342
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
343
|
-
await user.click(trigger1);
|
|
344
|
-
|
|
345
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
346
|
-
|
|
347
|
-
// Search for "React" - should find all React options
|
|
348
|
-
fireEvent.change(searchInput, { target: { value: 'React' } });
|
|
349
|
-
expect(searchInput).toHaveValue('React');
|
|
350
|
-
|
|
351
|
-
// Should find items starting with "React"
|
|
352
|
-
const items = screen.getAllByTestId('select-item');
|
|
353
|
-
expect(items.length).toBeGreaterThan(0);
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
it('handles partial word matches', async () => {
|
|
357
|
-
renderWithProviders(
|
|
358
|
-
<Select>
|
|
359
|
-
<SelectTrigger>
|
|
360
|
-
<SelectValue placeholder="Select an option" />
|
|
361
|
-
</SelectTrigger>
|
|
362
|
-
<SelectContent searchable searchStrategy="startsWith">
|
|
363
|
-
<SelectItem value="javascript">JavaScript</SelectItem>
|
|
364
|
-
<SelectItem value="typescript">TypeScript</SelectItem>
|
|
365
|
-
<SelectItem value="python">Python</SelectItem>
|
|
366
|
-
</SelectContent>
|
|
367
|
-
</Select>
|
|
368
|
-
);
|
|
369
|
-
|
|
370
|
-
// Click trigger to open the select
|
|
371
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
372
|
-
await user.click(trigger1);
|
|
373
|
-
|
|
374
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
375
|
-
|
|
376
|
-
// Search for "Java" - should find JavaScript
|
|
377
|
-
fireEvent.change(searchInput, { target: { value: 'Java' } });
|
|
378
|
-
expect(searchInput).toHaveValue('Java');
|
|
379
|
-
|
|
380
|
-
// Search for "Type" - should find TypeScript
|
|
381
|
-
await user.clear(searchInput, { delay: 0 });
|
|
382
|
-
fireEvent.change(searchInput, { target: { value: 'Type' } });
|
|
383
|
-
expect(searchInput).toHaveValue('Type');
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
describe('Exact Search Strategy', () => {
|
|
388
|
-
it('finds options that exactly match search term', async () => {
|
|
389
|
-
renderWithProviders(
|
|
390
|
-
<Select>
|
|
391
|
-
<SelectTrigger>
|
|
392
|
-
<SelectValue placeholder="Select an option" />
|
|
393
|
-
</SelectTrigger>
|
|
394
|
-
<SelectContent searchable searchStrategy="exact">
|
|
395
|
-
<SelectItem value="react">React</SelectItem>
|
|
396
|
-
<SelectItem value="react-native">React Native</SelectItem>
|
|
397
|
-
<SelectItem value="react-query">React Query</SelectItem>
|
|
398
|
-
<SelectItem value="vue">Vue</SelectItem>
|
|
399
|
-
</SelectContent>
|
|
400
|
-
</Select>
|
|
401
|
-
);
|
|
402
|
-
|
|
403
|
-
// Click trigger to open the select
|
|
404
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
405
|
-
await user.click(trigger1);
|
|
406
|
-
|
|
407
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
408
|
-
|
|
409
|
-
// Exact match for "React"
|
|
410
|
-
fireEvent.change(searchInput, { target: { value: 'React' } });
|
|
411
|
-
expect(searchInput).toHaveValue('React');
|
|
412
|
-
|
|
413
|
-
// Exact match for "React Native"
|
|
414
|
-
await user.clear(searchInput, { delay: 0 });
|
|
415
|
-
fireEvent.change(searchInput, { target: { value: 'React Native' } });
|
|
416
|
-
expect(searchInput).toHaveValue('React Native');
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
it('handles case-sensitive exact matches', async () => {
|
|
420
|
-
renderWithProviders(
|
|
421
|
-
<Select>
|
|
422
|
-
<SelectTrigger>
|
|
423
|
-
<SelectValue placeholder="Select an option" />
|
|
424
|
-
</SelectTrigger>
|
|
425
|
-
<SelectContent searchable searchStrategy="exact" caseSensitive>
|
|
426
|
-
<SelectItem value="React">React</SelectItem>
|
|
427
|
-
<SelectItem value="react">react</SelectItem>
|
|
428
|
-
<SelectItem value="REACT">REACT</SelectItem>
|
|
429
|
-
</SelectContent>
|
|
430
|
-
</Select>
|
|
431
|
-
);
|
|
432
|
-
|
|
433
|
-
// Click trigger to open the select
|
|
434
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
435
|
-
await user.click(trigger1);
|
|
436
|
-
|
|
437
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
438
|
-
|
|
439
|
-
// Case-sensitive exact matches
|
|
440
|
-
fireEvent.change(searchInput, { target: { value: 'React' } });
|
|
441
|
-
expect(searchInput).toHaveValue('React');
|
|
442
|
-
|
|
443
|
-
await user.clear(searchInput, { delay: 0 });
|
|
444
|
-
fireEvent.change(searchInput, { target: { value: 'react' } });
|
|
445
|
-
expect(searchInput).toHaveValue('react');
|
|
446
|
-
});
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
describe('Fuzzy Search Strategy', () => {
|
|
450
|
-
it('finds options with fuzzy matching', async () => {
|
|
451
|
-
renderWithProviders(
|
|
452
|
-
<Select>
|
|
453
|
-
<SelectTrigger>
|
|
454
|
-
<SelectValue placeholder="Select an option" />
|
|
455
|
-
</SelectTrigger>
|
|
456
|
-
<SelectContent searchable searchStrategy="fuzzy">
|
|
457
|
-
<SelectItem value="javascript">JavaScript</SelectItem>
|
|
458
|
-
<SelectItem value="typescript">TypeScript</SelectItem>
|
|
459
|
-
<SelectItem value="python">Python</SelectItem>
|
|
460
|
-
<SelectItem value="react">React</SelectItem>
|
|
461
|
-
</SelectContent>
|
|
462
|
-
</Select>
|
|
463
|
-
);
|
|
464
|
-
|
|
465
|
-
// Click trigger to open the select
|
|
466
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
467
|
-
await user.click(trigger1);
|
|
468
|
-
|
|
469
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
470
|
-
|
|
471
|
-
// Fuzzy search with typos
|
|
472
|
-
fireEvent.change(searchInput, { target: { value: 'javascrpt' } }); // Missing 'i'
|
|
473
|
-
expect(searchInput).toHaveValue('javascrpt');
|
|
474
|
-
|
|
475
|
-
await user.clear(searchInput, { delay: 0 });
|
|
476
|
-
fireEvent.change(searchInput, { target: { value: 'typescrpt' } }); // Missing 'i'
|
|
477
|
-
expect(searchInput).toHaveValue('typescrpt');
|
|
478
|
-
|
|
479
|
-
await user.clear(searchInput, { delay: 0 });
|
|
480
|
-
fireEvent.change(searchInput, { target: { value: 'pythn' } }); // Missing 'o'
|
|
481
|
-
expect(searchInput).toHaveValue('pythn');
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
it('handles partial fuzzy matches', async () => {
|
|
485
|
-
renderWithProviders(
|
|
486
|
-
<Select>
|
|
487
|
-
<SelectTrigger>
|
|
488
|
-
<SelectValue placeholder="Select an option" />
|
|
489
|
-
</SelectTrigger>
|
|
490
|
-
<SelectContent searchable searchStrategy="fuzzy">
|
|
491
|
-
<SelectItem value="react">React</SelectItem>
|
|
492
|
-
<SelectItem value="react-native">React Native</SelectItem>
|
|
493
|
-
<SelectItem value="react-query">React Query</SelectItem>
|
|
494
|
-
<SelectItem value="vue">Vue</SelectItem>
|
|
495
|
-
</SelectContent>
|
|
496
|
-
</Select>
|
|
497
|
-
);
|
|
498
|
-
|
|
499
|
-
// Click trigger to open the select
|
|
500
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
501
|
-
await user.click(trigger1);
|
|
502
|
-
|
|
503
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
504
|
-
|
|
505
|
-
// Partial fuzzy matches
|
|
506
|
-
fireEvent.change(searchInput, { target: { value: 'rc' } }); // Should match React
|
|
507
|
-
expect(searchInput).toHaveValue('rc');
|
|
508
|
-
|
|
509
|
-
await user.clear(searchInput, { delay: 0 });
|
|
510
|
-
fireEvent.change(searchInput, { target: { value: 'rn' } }); // Should match React Native
|
|
511
|
-
expect(searchInput).toHaveValue('rn');
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
it('handles fuzzy search with special characters', async () => {
|
|
515
|
-
renderWithProviders(
|
|
516
|
-
<Select>
|
|
517
|
-
<SelectTrigger>
|
|
518
|
-
<SelectValue placeholder="Select an option" />
|
|
519
|
-
</SelectTrigger>
|
|
520
|
-
<SelectContent searchable searchStrategy="fuzzy">
|
|
521
|
-
<SelectItem value="c++">C++ Programming</SelectItem>
|
|
522
|
-
<SelectItem value="c#">C# Programming</SelectItem>
|
|
523
|
-
<SelectItem value="react-js">React.js Framework</SelectItem>
|
|
524
|
-
<SelectItem value="node-js">Node.js Runtime</SelectItem>
|
|
525
|
-
</SelectContent>
|
|
526
|
-
</Select>
|
|
527
|
-
);
|
|
528
|
-
|
|
529
|
-
// Click trigger to open the select
|
|
530
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
531
|
-
await user.click(trigger1);
|
|
532
|
-
|
|
533
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
534
|
-
|
|
535
|
-
// Fuzzy search with special characters
|
|
536
|
-
fireEvent.change(searchInput, { target: { value: 'cpp' } }); // Should match C++
|
|
537
|
-
expect(searchInput).toHaveValue('cpp');
|
|
538
|
-
|
|
539
|
-
await user.clear(searchInput, { delay: 0 });
|
|
540
|
-
fireEvent.change(searchInput, { target: { value: 'cs' } }); // Should match C#
|
|
541
|
-
expect(searchInput).toHaveValue('cs');
|
|
542
|
-
});
|
|
543
|
-
});
|
|
544
|
-
|
|
545
|
-
describe('Search Field Configuration', () => {
|
|
546
|
-
it('searches in label field by default', async () => {
|
|
547
|
-
renderWithProviders(
|
|
548
|
-
<Select>
|
|
549
|
-
<SelectTrigger>
|
|
550
|
-
<SelectValue placeholder="Select an option" />
|
|
551
|
-
</SelectTrigger>
|
|
552
|
-
<SelectContent searchable searchFields={['label']}>
|
|
553
|
-
<SelectItem value="js">JavaScript</SelectItem>
|
|
554
|
-
<SelectItem value="ts">TypeScript</SelectItem>
|
|
555
|
-
<SelectItem value="py">Python</SelectItem>
|
|
556
|
-
</SelectContent>
|
|
557
|
-
</Select>
|
|
558
|
-
);
|
|
559
|
-
|
|
560
|
-
// Click trigger to open the select
|
|
561
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
562
|
-
await user.click(trigger1);
|
|
563
|
-
|
|
564
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
565
|
-
|
|
566
|
-
fireEvent.change(searchInput, { target: { value: 'JavaScript' } });
|
|
567
|
-
expect(searchInput).toHaveValue('JavaScript');
|
|
568
|
-
|
|
569
|
-
await user.clear(searchInput, { delay: 0 });
|
|
570
|
-
fireEvent.change(searchInput, { target: { value: 'TypeScript' } });
|
|
571
|
-
expect(searchInput).toHaveValue('TypeScript');
|
|
572
|
-
});
|
|
573
|
-
|
|
574
|
-
it('searches in value field when configured', async () => {
|
|
575
|
-
renderWithProviders(
|
|
576
|
-
<Select>
|
|
577
|
-
<SelectTrigger>
|
|
578
|
-
<SelectValue placeholder="Select an option" />
|
|
579
|
-
</SelectTrigger>
|
|
580
|
-
<SelectContent searchable searchFields={['value']}>
|
|
581
|
-
<SelectItem value="react">React Framework</SelectItem>
|
|
582
|
-
<SelectItem value="vue">Vue Framework</SelectItem>
|
|
583
|
-
<SelectItem value="angular">Angular Framework</SelectItem>
|
|
584
|
-
</SelectContent>
|
|
585
|
-
</Select>
|
|
586
|
-
);
|
|
587
|
-
|
|
588
|
-
// Click trigger to open the select
|
|
589
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
590
|
-
await user.click(trigger1);
|
|
591
|
-
|
|
592
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
593
|
-
|
|
594
|
-
fireEvent.change(searchInput, { target: { value: 'react' } });
|
|
595
|
-
expect(searchInput).toHaveValue('react');
|
|
596
|
-
|
|
597
|
-
await user.clear(searchInput, { delay: 0 });
|
|
598
|
-
fireEvent.change(searchInput, { target: { value: 'vue' } });
|
|
599
|
-
expect(searchInput).toHaveValue('vue');
|
|
600
|
-
});
|
|
601
|
-
|
|
602
|
-
it('searches in multiple fields', async () => {
|
|
603
|
-
renderWithProviders(
|
|
604
|
-
<Select>
|
|
605
|
-
<SelectTrigger>
|
|
606
|
-
<SelectValue placeholder="Select an option" />
|
|
607
|
-
</SelectTrigger>
|
|
608
|
-
<SelectContent searchable searchFields={['label', 'value']}>
|
|
609
|
-
<SelectItem value="react">React Framework</SelectItem>
|
|
610
|
-
<SelectItem value="vue">Vue Framework</SelectItem>
|
|
611
|
-
<SelectItem value="angular">Angular Framework</SelectItem>
|
|
612
|
-
</SelectContent>
|
|
613
|
-
</Select>
|
|
614
|
-
);
|
|
615
|
-
|
|
616
|
-
// Click trigger to open the select
|
|
617
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
618
|
-
await user.click(trigger1);
|
|
619
|
-
|
|
620
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
621
|
-
|
|
622
|
-
// Search in both label and value
|
|
623
|
-
fireEvent.change(searchInput, { target: { value: 'react' } });
|
|
624
|
-
expect(searchInput).toHaveValue('react');
|
|
625
|
-
|
|
626
|
-
await user.clear(searchInput, { delay: 0 });
|
|
627
|
-
fireEvent.change(searchInput, { target: { value: 'Framework' } });
|
|
628
|
-
expect(searchInput).toHaveValue('Framework');
|
|
629
|
-
});
|
|
630
|
-
});
|
|
631
|
-
|
|
632
|
-
describe('Search Performance', () => {
|
|
633
|
-
it('handles large datasets efficiently', async () => {
|
|
634
|
-
const largeOptions = Array.from({ length: 1000 }, (_, i) => (
|
|
635
|
-
<SelectItem key={i} value={`option-${i}`}>
|
|
636
|
-
Option {i + 1} - {Math.random().toString(36).substring(7)}
|
|
637
|
-
</SelectItem>
|
|
638
|
-
));
|
|
639
|
-
|
|
640
|
-
renderWithProviders(
|
|
641
|
-
<Select>
|
|
642
|
-
<SelectTrigger>
|
|
643
|
-
<SelectValue placeholder="Select an option" />
|
|
644
|
-
</SelectTrigger>
|
|
645
|
-
<SelectContent searchable debounceMs={50}>
|
|
646
|
-
{largeOptions}
|
|
647
|
-
</SelectContent>
|
|
648
|
-
</Select>
|
|
649
|
-
);
|
|
650
|
-
|
|
651
|
-
// Click trigger to open the select
|
|
652
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
653
|
-
await user.click(trigger1);
|
|
654
|
-
|
|
655
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
656
|
-
|
|
657
|
-
// Test search performance with large dataset
|
|
658
|
-
fireEvent.change(searchInput, { target: { value: 'Option 500' } });
|
|
659
|
-
expect(searchInput).toHaveValue('Option 500');
|
|
660
|
-
|
|
661
|
-
// Should not cause performance issues
|
|
662
|
-
expect(screen.getByTestId('select-search-input')).toBeInTheDocument();
|
|
663
|
-
});
|
|
664
|
-
|
|
665
|
-
it('handles rapid search input changes', async () => {
|
|
666
|
-
renderWithProviders(
|
|
667
|
-
<Select>
|
|
668
|
-
<SelectTrigger>
|
|
669
|
-
<SelectValue placeholder="Select an option" />
|
|
670
|
-
</SelectTrigger>
|
|
671
|
-
<SelectContent searchable debounceMs={100}>
|
|
672
|
-
<SelectItem value="option1">Option 1</SelectItem>
|
|
673
|
-
<SelectItem value="option2">Option 2</SelectItem>
|
|
674
|
-
<SelectItem value="option3">Option 3</SelectItem>
|
|
675
|
-
</SelectContent>
|
|
676
|
-
</Select>
|
|
677
|
-
);
|
|
678
|
-
|
|
679
|
-
// Click trigger to open the select
|
|
680
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
681
|
-
await user.click(trigger1);
|
|
682
|
-
|
|
683
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
684
|
-
|
|
685
|
-
// Rapid typing and clearing
|
|
686
|
-
fireEvent.change(searchInput, { target: { value: 'a' } });
|
|
687
|
-
await user.clear(searchInput, { delay: 0 });
|
|
688
|
-
fireEvent.change(searchInput, { target: { value: 'b' } });
|
|
689
|
-
await user.clear(searchInput, { delay: 0 });
|
|
690
|
-
fireEvent.change(searchInput, { target: { value: 'c' } });
|
|
691
|
-
await user.clear(searchInput, { delay: 0 });
|
|
692
|
-
fireEvent.change(searchInput, { target: { value: 'd' } });
|
|
693
|
-
|
|
694
|
-
expect(searchInput).toHaveValue('d');
|
|
695
|
-
});
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
describe('Search Edge Cases', () => {
|
|
699
|
-
it('handles empty search term', async () => {
|
|
700
|
-
renderWithProviders(
|
|
701
|
-
<Select>
|
|
702
|
-
<SelectTrigger>
|
|
703
|
-
<SelectValue placeholder="Select an option" />
|
|
704
|
-
</SelectTrigger>
|
|
705
|
-
<SelectContent searchable>
|
|
706
|
-
<SelectItem value="option1">Option 1</SelectItem>
|
|
707
|
-
<SelectItem value="option2">Option 2</SelectItem>
|
|
708
|
-
</SelectContent>
|
|
709
|
-
</Select>
|
|
710
|
-
);
|
|
711
|
-
|
|
712
|
-
// Click trigger to open the select
|
|
713
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
714
|
-
await user.click(trigger1);
|
|
715
|
-
|
|
716
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
717
|
-
|
|
718
|
-
// Empty search should show all options
|
|
719
|
-
expect(searchInput).toHaveValue('');
|
|
720
|
-
|
|
721
|
-
const items = screen.getAllByTestId('select-item');
|
|
722
|
-
expect(items).toHaveLength(2);
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
it('handles search with whitespace', async () => {
|
|
726
|
-
renderWithProviders(
|
|
727
|
-
<Select>
|
|
728
|
-
<SelectTrigger>
|
|
729
|
-
<SelectValue placeholder="Select an option" />
|
|
730
|
-
</SelectTrigger>
|
|
731
|
-
<SelectContent searchable>
|
|
732
|
-
<SelectItem value="react">React Framework</SelectItem>
|
|
733
|
-
<SelectItem value="vue">Vue Framework</SelectItem>
|
|
734
|
-
</SelectContent>
|
|
735
|
-
</Select>
|
|
736
|
-
);
|
|
737
|
-
|
|
738
|
-
// Click trigger to open the select
|
|
739
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
740
|
-
await user.click(trigger1);
|
|
741
|
-
|
|
742
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
743
|
-
|
|
744
|
-
// Search with leading/trailing whitespace
|
|
745
|
-
fireEvent.change(searchInput, { target: { value: ' React ' } });
|
|
746
|
-
expect(searchInput).toHaveValue(' React ');
|
|
747
|
-
});
|
|
748
|
-
|
|
749
|
-
it('handles search with unicode characters', async () => {
|
|
750
|
-
renderWithProviders(
|
|
751
|
-
<Select>
|
|
752
|
-
<SelectTrigger>
|
|
753
|
-
<SelectValue placeholder="Select an option" />
|
|
754
|
-
</SelectTrigger>
|
|
755
|
-
<SelectContent searchable>
|
|
756
|
-
<SelectItem value="cafe">café</SelectItem>
|
|
757
|
-
<SelectItem value="umlaut">über</SelectItem>
|
|
758
|
-
<SelectItem value="emoji">🚀 React</SelectItem>
|
|
759
|
-
</SelectContent>
|
|
760
|
-
</Select>
|
|
761
|
-
);
|
|
762
|
-
|
|
763
|
-
// Click trigger to open the select
|
|
764
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
765
|
-
await user.click(trigger1);
|
|
766
|
-
|
|
767
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
768
|
-
|
|
769
|
-
// Search with unicode characters
|
|
770
|
-
fireEvent.change(searchInput, { target: { value: 'café' } });
|
|
771
|
-
expect(searchInput).toHaveValue('café');
|
|
772
|
-
|
|
773
|
-
await user.clear(searchInput, { delay: 0 });
|
|
774
|
-
fireEvent.change(searchInput, { target: { value: 'über' } });
|
|
775
|
-
expect(searchInput).toHaveValue('über');
|
|
776
|
-
|
|
777
|
-
await user.clear(searchInput, { delay: 0 });
|
|
778
|
-
fireEvent.change(searchInput, { target: { value: '🚀' } });
|
|
779
|
-
expect(searchInput).toHaveValue('🚀');
|
|
780
|
-
});
|
|
781
|
-
|
|
782
|
-
it('handles search with special regex characters', async () => {
|
|
783
|
-
renderWithProviders(
|
|
784
|
-
<Select>
|
|
785
|
-
<SelectTrigger>
|
|
786
|
-
<SelectValue placeholder="Select an option" />
|
|
787
|
-
</SelectTrigger>
|
|
788
|
-
<SelectContent searchable>
|
|
789
|
-
<SelectItem value="regex-test">Regex Test</SelectItem>
|
|
790
|
-
<SelectItem value="special-chars">Special Characters: .*+?^${}()|[\]\\</SelectItem>
|
|
791
|
-
</SelectContent>
|
|
792
|
-
</Select>
|
|
793
|
-
);
|
|
794
|
-
|
|
795
|
-
// Click trigger to open the select
|
|
796
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
797
|
-
await user.click(trigger1);
|
|
798
|
-
|
|
799
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
800
|
-
|
|
801
|
-
// Search with special regex characters (using fireEvent to avoid userEvent parsing issues)
|
|
802
|
-
fireEvent.change(searchInput, { target: { value: '.*+?^${}()|[\\]\\\\' } });
|
|
803
|
-
expect(searchInput).toHaveValue('.*+?^${}()|[\\]\\\\');
|
|
804
|
-
|
|
805
|
-
await user.clear(searchInput, { delay: 0 });
|
|
806
|
-
fireEvent.change(searchInput, { target: { value: 'Regex' } });
|
|
807
|
-
expect(searchInput).toHaveValue('Regex');
|
|
808
|
-
});
|
|
809
|
-
});
|
|
810
|
-
|
|
811
|
-
describe('Search Result Highlighting', () => {
|
|
812
|
-
it('handles text highlighting in search results', async () => {
|
|
813
|
-
renderWithProviders(
|
|
814
|
-
<Select>
|
|
815
|
-
<SelectTrigger>
|
|
816
|
-
<SelectValue placeholder="Select an option" />
|
|
817
|
-
</SelectTrigger>
|
|
818
|
-
<SelectContent searchable highlightMatches>
|
|
819
|
-
<SelectItem value="react">React Framework</SelectItem>
|
|
820
|
-
<SelectItem value="vue">Vue Framework</SelectItem>
|
|
821
|
-
<SelectItem value="angular">Angular Framework</SelectItem>
|
|
822
|
-
</SelectContent>
|
|
823
|
-
</Select>
|
|
824
|
-
);
|
|
825
|
-
|
|
826
|
-
// Click trigger to open the select
|
|
827
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
828
|
-
await user.click(trigger1);
|
|
829
|
-
|
|
830
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
831
|
-
|
|
832
|
-
fireEvent.change(searchInput, { target: { value: 'React' } });
|
|
833
|
-
expect(searchInput).toHaveValue('React');
|
|
834
|
-
|
|
835
|
-
// Should highlight matching text
|
|
836
|
-
const items = screen.getAllByTestId('select-item');
|
|
837
|
-
expect(items.length).toBeGreaterThan(0);
|
|
838
|
-
});
|
|
839
|
-
|
|
840
|
-
it('handles highlighting with complex content', async () => {
|
|
841
|
-
renderWithProviders(
|
|
842
|
-
<Select>
|
|
843
|
-
<SelectTrigger>
|
|
844
|
-
<SelectValue placeholder="Select an option" />
|
|
845
|
-
</SelectTrigger>
|
|
846
|
-
<SelectContent searchable highlightMatches>
|
|
847
|
-
<SelectItem value="complex1">
|
|
848
|
-
<span>🚀</span>
|
|
849
|
-
<strong>React</strong>
|
|
850
|
-
<span>Framework</span>
|
|
851
|
-
</SelectItem>
|
|
852
|
-
<SelectItem value="complex2">
|
|
853
|
-
<span>⚡</span>
|
|
854
|
-
<strong>Vue</strong>
|
|
855
|
-
<span>Framework</span>
|
|
856
|
-
</SelectItem>
|
|
857
|
-
</SelectContent>
|
|
858
|
-
</Select>
|
|
859
|
-
);
|
|
860
|
-
|
|
861
|
-
// Click trigger to open the select
|
|
862
|
-
const trigger1 = screen.getByTestId('select-trigger');
|
|
863
|
-
await user.click(trigger1);
|
|
864
|
-
|
|
865
|
-
const searchInput = screen.getByTestId('select-search-input');
|
|
866
|
-
|
|
867
|
-
fireEvent.change(searchInput, { target: { value: 'React' } });
|
|
868
|
-
expect(searchInput).toHaveValue('React');
|
|
869
|
-
|
|
870
|
-
await user.clear(searchInput, { delay: 0 });
|
|
871
|
-
fireEvent.change(searchInput, { target: { value: 'Framework' } });
|
|
872
|
-
expect(searchInput).toHaveValue('Framework');
|
|
873
|
-
});
|
|
874
|
-
});
|
|
875
|
-
describe('Select Error Handling', () => {
|
|
876
|
-
const user = userEvent.setup();
|
|
877
|
-
let restoreConsole: (() => void) | null = null;
|
|
878
|
-
|
|
879
|
-
beforeEach(() => {
|
|
880
|
-
restoreConsole = errorTestingUtils.suppressConsoleErrors();
|
|
881
|
-
});
|
|
882
|
-
|
|
883
|
-
afterEach(() => {
|
|
884
|
-
if (restoreConsole) {
|
|
885
|
-
restoreConsole();
|
|
886
|
-
}
|
|
887
|
-
});
|
|
888
|
-
|
|
889
|
-
it('should handle component errors gracefully', () => {
|
|
890
|
-
const ErrorComponent = () => {
|
|
891
|
-
throw new Error('Select component error');
|
|
892
|
-
};
|
|
893
|
-
|
|
894
|
-
renderWithProviders(
|
|
895
|
-
<TestErrorBoundary>
|
|
896
|
-
<ErrorComponent />
|
|
897
|
-
</TestErrorBoundary>
|
|
898
|
-
);
|
|
899
|
-
|
|
900
|
-
expect(screen.getByTestId('error-boundary')).toBeInTheDocument();
|
|
901
|
-
expect(screen.getByText('Error: Select component error')).toBeInTheDocument();
|
|
902
|
-
});
|
|
903
|
-
|
|
904
|
-
it('should handle async errors', async () => {
|
|
905
|
-
const AsyncErrorComponent = ({ shouldFail }: { shouldFail: boolean }) => {
|
|
906
|
-
const [error, setError] = React.useState<Error | null>(null);
|
|
907
|
-
|
|
908
|
-
React.useEffect(() => {
|
|
909
|
-
if (shouldFail) {
|
|
910
|
-
setError(new Error('Async error'));
|
|
911
|
-
}
|
|
912
|
-
}, [shouldFail]);
|
|
913
|
-
|
|
914
|
-
if (error) {
|
|
915
|
-
throw error;
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
return <div>Async component</div>;
|
|
919
|
-
};
|
|
920
|
-
|
|
921
|
-
renderWithProviders(
|
|
922
|
-
<TestErrorBoundary>
|
|
923
|
-
<AsyncErrorComponent shouldFail={true} />
|
|
924
|
-
</TestErrorBoundary>
|
|
925
|
-
);
|
|
926
|
-
|
|
927
|
-
await waitFor(() => {
|
|
928
|
-
expect(screen.getByTestId('error-boundary')).toBeInTheDocument();
|
|
929
|
-
});
|
|
930
|
-
});
|
|
931
|
-
|
|
932
|
-
it('should handle user interaction errors', async () => {
|
|
933
|
-
const ErrorComponent = errorTestingUtils.createErrorThrowingComponent(
|
|
934
|
-
'Select interaction error',
|
|
935
|
-
'click'
|
|
936
|
-
);
|
|
937
|
-
|
|
938
|
-
renderWithProviders(
|
|
939
|
-
<TestErrorBoundary>
|
|
940
|
-
<ErrorComponent />
|
|
941
|
-
</TestErrorBoundary>
|
|
942
|
-
);
|
|
943
|
-
|
|
944
|
-
await user.click(screen.getByTestId('error-button'));
|
|
945
|
-
|
|
946
|
-
await waitFor(() => {
|
|
947
|
-
expect(screen.getByTestId('error-display')).toBeInTheDocument();
|
|
948
|
-
});
|
|
949
|
-
});
|
|
950
|
-
|
|
951
|
-
it('should recover from errors when props change', async () => {
|
|
952
|
-
const TestComponent = ({ shouldError }: { shouldError: boolean }) => {
|
|
953
|
-
if (shouldError) {
|
|
954
|
-
throw new Error('Select prop error');
|
|
955
|
-
}
|
|
956
|
-
return <div>Normal content</div>;
|
|
957
|
-
};
|
|
958
|
-
|
|
959
|
-
await errorTestingUtils.testErrorRecovery(
|
|
960
|
-
TestComponent,
|
|
961
|
-
{ shouldError: true },
|
|
962
|
-
{ shouldError: false }
|
|
963
|
-
);
|
|
964
|
-
|
|
965
|
-
expect(screen.getByText('Normal content')).toBeInTheDocument();
|
|
966
|
-
});
|
|
967
|
-
});
|
|
968
|
-
});
|