@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,820 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Form Accessibility Tests
|
|
3
|
-
* @package @jmruthers/pace-core
|
|
4
|
-
* @module Form
|
|
5
|
-
* @since 0.1.0
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import React from 'react';
|
|
9
|
-
import { screen, waitFor } from '@testing-library/react';
|
|
10
|
-
import { edgeCaseUtils } from '../../__tests__/EdgeCaseTesting.enhanced.test';
|
|
11
|
-
import { errorTestingUtils, TestErrorBoundary } from '../../__tests__/ErrorTesting.enhanced.test';
|
|
12
|
-
import userEvent from '@testing-library/user-event';
|
|
13
|
-
import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
|
|
14
|
-
import { renderWithProviders } from '../../../__tests__/shared';
|
|
15
|
-
import { axe, toHaveNoViolations } from 'jest-axe';
|
|
16
|
-
import { z } from 'zod';
|
|
17
|
-
import { Form, FormField, FormErrorSummary, FormLiveRegion, FormFieldset } from '../index';
|
|
18
|
-
|
|
19
|
-
// Extend expect to include axe matchers
|
|
20
|
-
expect.extend(toHaveNoViolations);
|
|
21
|
-
|
|
22
|
-
// Mock console.error to reduce noise in tests
|
|
23
|
-
const originalError = console.error;
|
|
24
|
-
beforeAll(() => {
|
|
25
|
-
console.error = (...args: any[]) => {
|
|
26
|
-
if (
|
|
27
|
-
typeof args[0] === 'string' &&
|
|
28
|
-
args[0].includes('Warning: ReactDOM.render is no longer supported')
|
|
29
|
-
) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
originalError.call(console, ...args);
|
|
33
|
-
};
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
afterAll(() => {
|
|
37
|
-
console.error = originalError;
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe('Form Accessibility', () => {
|
|
41
|
-
const user = userEvent.setup();
|
|
42
|
-
|
|
43
|
-
describe('Form Component', () => {
|
|
44
|
-
it('should have no accessibility violations', async () => {
|
|
45
|
-
const schema = z.object({
|
|
46
|
-
name: z.string().min(1, 'Name is required'),
|
|
47
|
-
email: z.string().email('Invalid email'),
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
const { container } = renderWithProviders(
|
|
51
|
-
<Form
|
|
52
|
-
schema={schema}
|
|
53
|
-
onSubmit={() => {}}
|
|
54
|
-
defaultValues={{ name: '', email: '' }}
|
|
55
|
-
>
|
|
56
|
-
<FormField name="name" label="Name" validation={{ required: true }} />
|
|
57
|
-
<FormField name="email" label="Email" type="email" validation={{ required: true }} />
|
|
58
|
-
<button type="submit">Submit</button>
|
|
59
|
-
</Form>
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
const results = await axe(container);
|
|
63
|
-
expect(results).toHaveNoViolations();
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should have proper form element', () => {
|
|
67
|
-
const { container } = renderWithProviders(
|
|
68
|
-
<Form onSubmit={() => {}}>
|
|
69
|
-
<FormField name="test" label="Test" />
|
|
70
|
-
<button type="submit">Submit</button>
|
|
71
|
-
</Form>
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
const form = container.querySelector('form');
|
|
75
|
-
expect(form).toBeInTheDocument();
|
|
76
|
-
// Note: HTML form elements don't need explicit role="form" as it's implicit
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should handle keyboard navigation properly', async () => {
|
|
80
|
-
const handleSubmit = vi.fn();
|
|
81
|
-
|
|
82
|
-
renderWithProviders(
|
|
83
|
-
<Form onSubmit={handleSubmit}>
|
|
84
|
-
<FormField name="name" label="Name" />
|
|
85
|
-
<FormField name="email" label="Email" type="email" />
|
|
86
|
-
<button type="submit">Submit</button>
|
|
87
|
-
</Form>
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
const nameInput = screen.getByLabelText('Name');
|
|
91
|
-
const emailInput = screen.getByLabelText('Email');
|
|
92
|
-
const submitButton = screen.getByRole('button', { name: 'Submit' });
|
|
93
|
-
|
|
94
|
-
// Tab navigation
|
|
95
|
-
await user.tab();
|
|
96
|
-
expect(nameInput).toHaveFocus();
|
|
97
|
-
|
|
98
|
-
await user.tab();
|
|
99
|
-
expect(emailInput).toHaveFocus();
|
|
100
|
-
|
|
101
|
-
await user.tab();
|
|
102
|
-
expect(submitButton).toHaveFocus();
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('should be accessible for screen readers', async () => {
|
|
106
|
-
const handleSubmit = vi.fn();
|
|
107
|
-
|
|
108
|
-
const { container } = renderWithProviders(
|
|
109
|
-
<Form onSubmit={handleSubmit}>
|
|
110
|
-
<FormField name="name" label="Name" />
|
|
111
|
-
<button type="submit">Submit</button>
|
|
112
|
-
</Form>
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
const form = container.querySelector('form');
|
|
116
|
-
expect(form).toBeInTheDocument();
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
describe('FormField Component', () => {
|
|
121
|
-
it('should have proper label-input association', () => {
|
|
122
|
-
renderWithProviders(
|
|
123
|
-
<Form onSubmit={() => {}}>
|
|
124
|
-
<FormField name="test" label="Test Field" />
|
|
125
|
-
</Form>
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
const label = screen.getByText('Test Field');
|
|
129
|
-
const input = screen.getByLabelText('Test Field');
|
|
130
|
-
|
|
131
|
-
expect(label).toBeInTheDocument();
|
|
132
|
-
expect(input).toBeInTheDocument();
|
|
133
|
-
expect(input).toHaveAttribute('id', 'test');
|
|
134
|
-
expect(label).toHaveAttribute('for', 'test');
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('should indicate required fields with asterisk and aria-label', () => {
|
|
138
|
-
renderWithProviders(
|
|
139
|
-
<Form onSubmit={() => {}}>
|
|
140
|
-
<FormField
|
|
141
|
-
name="required"
|
|
142
|
-
label="Required Field"
|
|
143
|
-
validation={{ required: true }}
|
|
144
|
-
/>
|
|
145
|
-
</Form>
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
const requiredIndicator = screen.getByText('*');
|
|
149
|
-
expect(requiredIndicator).toBeInTheDocument();
|
|
150
|
-
expect(requiredIndicator).toHaveAttribute('aria-label', 'required');
|
|
151
|
-
expect(requiredIndicator).toHaveClass('text-destructive');
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it('should display error messages with proper ARIA attributes', async () => {
|
|
155
|
-
const schema = z.object({
|
|
156
|
-
test: z.string().min(1, 'Required'),
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
renderWithProviders(
|
|
160
|
-
<Form schema={schema} onSubmit={() => {}}>
|
|
161
|
-
<FormField name="test" label="Test Field" />
|
|
162
|
-
<button type="submit">Submit</button>
|
|
163
|
-
</Form>
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
const submitButton = screen.getByRole('button', { name: 'Submit' });
|
|
167
|
-
await user.click(submitButton);
|
|
168
|
-
|
|
169
|
-
await waitFor(() => {
|
|
170
|
-
const errorMessage = screen.getByText('Required');
|
|
171
|
-
expect(errorMessage).toBeInTheDocument();
|
|
172
|
-
expect(errorMessage).toHaveAttribute('role', 'alert');
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('should apply error styling to inputs with validation errors', async () => {
|
|
177
|
-
const schema = z.object({
|
|
178
|
-
test: z.string().min(1, 'This field is required'),
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
renderWithProviders(
|
|
182
|
-
<Form schema={schema} onSubmit={() => {}}>
|
|
183
|
-
<FormField name="test" label="Test Field" />
|
|
184
|
-
<button type="submit">Submit</button>
|
|
185
|
-
</Form>
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
const submitButton = screen.getByRole('button', { name: 'Submit' });
|
|
189
|
-
await user.click(submitButton);
|
|
190
|
-
|
|
191
|
-
await waitFor(() => {
|
|
192
|
-
const input = screen.getByLabelText('Test Field');
|
|
193
|
-
expect(input).toHaveClass('border-destructive');
|
|
194
|
-
expect(input).toHaveClass('focus-visible:ring-destructive');
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('should support custom input types with proper accessibility', () => {
|
|
199
|
-
renderWithProviders(
|
|
200
|
-
<Form onSubmit={() => {}}>
|
|
201
|
-
<FormField name="email" label="Email" type="email" />
|
|
202
|
-
<FormField name="password" label="Password" type="password" />
|
|
203
|
-
<FormField name="number" label="Age" type="number" />
|
|
204
|
-
</Form>
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
const emailInput = screen.getByLabelText('Email');
|
|
208
|
-
const passwordInput = screen.getByLabelText('Password');
|
|
209
|
-
const numberInput = screen.getByLabelText('Age');
|
|
210
|
-
|
|
211
|
-
expect(emailInput).toHaveAttribute('type', 'email');
|
|
212
|
-
expect(passwordInput).toHaveAttribute('type', 'password');
|
|
213
|
-
expect(numberInput).toHaveAttribute('type', 'number');
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('should support placeholder text for better UX', () => {
|
|
217
|
-
renderWithProviders(
|
|
218
|
-
<Form onSubmit={() => {}}>
|
|
219
|
-
<FormField
|
|
220
|
-
name="search"
|
|
221
|
-
label="Search"
|
|
222
|
-
placeholder="Enter search term..."
|
|
223
|
-
/>
|
|
224
|
-
</Form>
|
|
225
|
-
);
|
|
226
|
-
|
|
227
|
-
const input = screen.getByPlaceholderText('Enter search term...');
|
|
228
|
-
expect(input).toBeInTheDocument();
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
it('should support disabled state with proper accessibility', () => {
|
|
232
|
-
renderWithProviders(
|
|
233
|
-
<Form onSubmit={() => {}}>
|
|
234
|
-
<FormField
|
|
235
|
-
name="disabled"
|
|
236
|
-
label="Disabled Field"
|
|
237
|
-
inputProps={{ disabled: true }}
|
|
238
|
-
/>
|
|
239
|
-
</Form>
|
|
240
|
-
);
|
|
241
|
-
|
|
242
|
-
const input = screen.getByLabelText('Disabled Field');
|
|
243
|
-
expect(input).toBeDisabled();
|
|
244
|
-
expect(input).toHaveClass('disabled:cursor-not-allowed');
|
|
245
|
-
expect(input).toHaveClass('disabled:opacity-50');
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
describe('FormErrorSummary Component', () => {
|
|
250
|
-
it('should have no accessibility violations', async () => {
|
|
251
|
-
const errors = {
|
|
252
|
-
name: { message: 'Name is required' },
|
|
253
|
-
email: { message: 'Invalid email format' },
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
const { container } = renderWithProviders(
|
|
257
|
-
<FormErrorSummary errors={errors} />
|
|
258
|
-
);
|
|
259
|
-
|
|
260
|
-
const results = await axe(container);
|
|
261
|
-
expect(results).toHaveNoViolations();
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it('should render error list with proper ARIA attributes', () => {
|
|
265
|
-
const errors = {
|
|
266
|
-
name: { message: 'Name is required' },
|
|
267
|
-
email: { message: 'Invalid email format' },
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
renderWithProviders(<FormErrorSummary errors={errors} />);
|
|
271
|
-
|
|
272
|
-
const alert = screen.getByRole('alert');
|
|
273
|
-
expect(alert).toBeInTheDocument();
|
|
274
|
-
|
|
275
|
-
const list = screen.getByRole('list');
|
|
276
|
-
expect(list).toBeInTheDocument();
|
|
277
|
-
|
|
278
|
-
const listItems = screen.getAllByRole('listitem');
|
|
279
|
-
expect(listItems).toHaveLength(2);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it('should not render when no errors are present', () => {
|
|
283
|
-
const { container } = renderWithProviders(<FormErrorSummary errors={{}} />);
|
|
284
|
-
// Check that the FormErrorSummary component itself doesn't render content
|
|
285
|
-
const errorSummary = container.querySelector('[data-testid="form-error-summary"]');
|
|
286
|
-
expect(errorSummary).toBeNull();
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it('should support custom title with proper heading structure', () => {
|
|
290
|
-
const errors = { name: { message: 'Name is required' } };
|
|
291
|
-
|
|
292
|
-
renderWithProviders(
|
|
293
|
-
<FormErrorSummary
|
|
294
|
-
errors={errors}
|
|
295
|
-
title="Please correct the following issues:"
|
|
296
|
-
/>
|
|
297
|
-
);
|
|
298
|
-
|
|
299
|
-
const heading = screen.getByRole('heading', { level: 3 });
|
|
300
|
-
expect(heading).toHaveTextContent('Please correct the following issues:');
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
it('should show field names when requested', () => {
|
|
304
|
-
const errors = {
|
|
305
|
-
name: { message: 'Name is required' },
|
|
306
|
-
email: { message: 'Invalid email format' },
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
renderWithProviders(<FormErrorSummary errors={errors} showFieldNames />);
|
|
310
|
-
|
|
311
|
-
expect(screen.getByText('name: Name is required')).toBeInTheDocument();
|
|
312
|
-
expect(screen.getByText('email: Invalid email format')).toBeInTheDocument();
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
describe('FormLiveRegion Component', () => {
|
|
317
|
-
it('should have no accessibility violations when rendered', async () => {
|
|
318
|
-
const mockForm = {
|
|
319
|
-
formState: {
|
|
320
|
-
isSubmitting: true,
|
|
321
|
-
isSubmitSuccessful: false,
|
|
322
|
-
errors: {},
|
|
323
|
-
isValid: false,
|
|
324
|
-
isDirty: false,
|
|
325
|
-
touchedFields: {},
|
|
326
|
-
},
|
|
327
|
-
} as any;
|
|
328
|
-
|
|
329
|
-
const { container } = renderWithProviders(
|
|
330
|
-
<FormLiveRegion form={mockForm} />
|
|
331
|
-
);
|
|
332
|
-
|
|
333
|
-
const results = await axe(container);
|
|
334
|
-
expect(results).toHaveNoViolations();
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
it('should render live region with proper ARIA attributes when there is a message', () => {
|
|
338
|
-
const mockForm = {
|
|
339
|
-
formState: {
|
|
340
|
-
isSubmitting: true,
|
|
341
|
-
isSubmitSuccessful: false,
|
|
342
|
-
errors: {},
|
|
343
|
-
isValid: false,
|
|
344
|
-
isDirty: false,
|
|
345
|
-
touchedFields: {},
|
|
346
|
-
},
|
|
347
|
-
} as any;
|
|
348
|
-
|
|
349
|
-
renderWithProviders(<FormLiveRegion form={mockForm} />);
|
|
350
|
-
|
|
351
|
-
const liveRegion = screen.getByRole('status');
|
|
352
|
-
expect(liveRegion).toHaveAttribute('aria-live', 'polite');
|
|
353
|
-
expect(liveRegion).toHaveAttribute('aria-atomic', 'true');
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
it('should support assertive politeness level', () => {
|
|
357
|
-
const mockForm = {
|
|
358
|
-
formState: {
|
|
359
|
-
isSubmitting: true,
|
|
360
|
-
isSubmitSuccessful: false,
|
|
361
|
-
errors: {},
|
|
362
|
-
isValid: false,
|
|
363
|
-
isDirty: false,
|
|
364
|
-
touchedFields: {},
|
|
365
|
-
},
|
|
366
|
-
} as any;
|
|
367
|
-
|
|
368
|
-
renderWithProviders(<FormLiveRegion form={mockForm} politeness="assertive" />);
|
|
369
|
-
|
|
370
|
-
const liveRegion = screen.getByRole('status');
|
|
371
|
-
expect(liveRegion).toHaveAttribute('aria-live', 'assertive');
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
it('should be positioned off-screen for screen readers', () => {
|
|
375
|
-
const mockForm = {
|
|
376
|
-
formState: {
|
|
377
|
-
isSubmitting: true,
|
|
378
|
-
isSubmitSuccessful: false,
|
|
379
|
-
errors: {},
|
|
380
|
-
isValid: false,
|
|
381
|
-
isDirty: false,
|
|
382
|
-
touchedFields: {},
|
|
383
|
-
},
|
|
384
|
-
} as any;
|
|
385
|
-
|
|
386
|
-
renderWithProviders(<FormLiveRegion form={mockForm} />);
|
|
387
|
-
|
|
388
|
-
const liveRegion = screen.getByRole('status');
|
|
389
|
-
expect(liveRegion).toHaveStyle({
|
|
390
|
-
position: 'absolute',
|
|
391
|
-
left: '-10000px',
|
|
392
|
-
width: '1px',
|
|
393
|
-
height: '1px',
|
|
394
|
-
overflow: 'hidden',
|
|
395
|
-
});
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
it('should not render when no message is present', () => {
|
|
399
|
-
const mockForm = {
|
|
400
|
-
formState: {
|
|
401
|
-
isSubmitting: false,
|
|
402
|
-
isSubmitSuccessful: false,
|
|
403
|
-
errors: {},
|
|
404
|
-
isValid: false,
|
|
405
|
-
isDirty: false,
|
|
406
|
-
touchedFields: {},
|
|
407
|
-
},
|
|
408
|
-
} as any;
|
|
409
|
-
|
|
410
|
-
const { container } = renderWithProviders(<FormLiveRegion form={mockForm} />);
|
|
411
|
-
// Check that the FormLiveRegion component itself doesn't render content
|
|
412
|
-
const liveRegion = container.querySelector('[data-testid="form-live-region"]');
|
|
413
|
-
expect(liveRegion).toBeNull();
|
|
414
|
-
});
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
describe('FormFieldset Component', () => {
|
|
418
|
-
it('should have no accessibility violations', async () => {
|
|
419
|
-
const { container } = renderWithProviders(
|
|
420
|
-
<Form onSubmit={() => {}}>
|
|
421
|
-
<FormFieldset legend="Personal Information">
|
|
422
|
-
<FormField name="name" label="Name" />
|
|
423
|
-
<FormField name="email" label="Email" />
|
|
424
|
-
</FormFieldset>
|
|
425
|
-
</Form>
|
|
426
|
-
);
|
|
427
|
-
|
|
428
|
-
const results = await axe(container);
|
|
429
|
-
expect(results).toHaveNoViolations();
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
it('should render fieldset with proper legend', () => {
|
|
433
|
-
renderWithProviders(
|
|
434
|
-
<Form onSubmit={() => {}}>
|
|
435
|
-
<FormFieldset legend="Personal Information">
|
|
436
|
-
<FormField name="name" label="Name" />
|
|
437
|
-
</FormFieldset>
|
|
438
|
-
</Form>
|
|
439
|
-
);
|
|
440
|
-
|
|
441
|
-
const fieldset = screen.getByRole('group');
|
|
442
|
-
expect(fieldset).toBeInTheDocument();
|
|
443
|
-
|
|
444
|
-
const legend = screen.getByText('Personal Information');
|
|
445
|
-
expect(legend).toBeInTheDocument();
|
|
446
|
-
});
|
|
447
|
-
|
|
448
|
-
it('should indicate required fieldsets with asterisk', () => {
|
|
449
|
-
renderWithProviders(
|
|
450
|
-
<Form onSubmit={() => {}}>
|
|
451
|
-
<FormFieldset legend="Personal Information" required>
|
|
452
|
-
<FormField name="name" label="Name" />
|
|
453
|
-
</FormFieldset>
|
|
454
|
-
</Form>
|
|
455
|
-
);
|
|
456
|
-
|
|
457
|
-
const requiredIndicator = screen.getByText('*');
|
|
458
|
-
expect(requiredIndicator).toBeInTheDocument();
|
|
459
|
-
expect(requiredIndicator).toHaveClass('text-destructive');
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
it('should support description with proper ARIA association', () => {
|
|
463
|
-
renderWithProviders(
|
|
464
|
-
<Form onSubmit={() => {}}>
|
|
465
|
-
<FormFieldset
|
|
466
|
-
legend="Personal Information"
|
|
467
|
-
description="Please provide your contact details"
|
|
468
|
-
>
|
|
469
|
-
<FormField name="name" label="Name" />
|
|
470
|
-
</FormFieldset>
|
|
471
|
-
</Form>
|
|
472
|
-
);
|
|
473
|
-
|
|
474
|
-
const fieldset = screen.getByRole('group');
|
|
475
|
-
const description = screen.getByText('Please provide your contact details');
|
|
476
|
-
|
|
477
|
-
expect(description).toBeInTheDocument();
|
|
478
|
-
expect(fieldset).toHaveAttribute('aria-describedby', description.id);
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
it('should support custom className and props', () => {
|
|
482
|
-
renderWithProviders(
|
|
483
|
-
<Form onSubmit={() => {}}>
|
|
484
|
-
<FormFieldset
|
|
485
|
-
legend="Test"
|
|
486
|
-
className="custom-class"
|
|
487
|
-
data-testid="test-fieldset"
|
|
488
|
-
>
|
|
489
|
-
<FormField name="name" label="Name" />
|
|
490
|
-
</FormFieldset>
|
|
491
|
-
</Form>
|
|
492
|
-
);
|
|
493
|
-
|
|
494
|
-
const fieldset = screen.getByTestId('test-fieldset');
|
|
495
|
-
expect(fieldset).toHaveClass('custom-class');
|
|
496
|
-
expect(fieldset).toHaveClass('space-y-4');
|
|
497
|
-
expect(fieldset).toHaveClass('border');
|
|
498
|
-
expect(fieldset).toHaveClass('border-input');
|
|
499
|
-
expect(fieldset).toHaveClass('rounded-lg');
|
|
500
|
-
expect(fieldset).toHaveClass('p-4');
|
|
501
|
-
});
|
|
502
|
-
});
|
|
503
|
-
|
|
504
|
-
describe('Form Integration Accessibility', () => {
|
|
505
|
-
it('should handle complex form validation with proper accessibility', async () => {
|
|
506
|
-
const schema = z.object({
|
|
507
|
-
name: z.string().min(1, 'Required'),
|
|
508
|
-
email: z.string().email('Invalid email format'),
|
|
509
|
-
age: z.number().min(18, 'Must be at least 18 years old'),
|
|
510
|
-
});
|
|
511
|
-
|
|
512
|
-
const handleSubmit = vi.fn();
|
|
513
|
-
|
|
514
|
-
renderWithProviders(
|
|
515
|
-
<Form schema={schema} onSubmit={handleSubmit}>
|
|
516
|
-
<FormFieldset legend="Personal Information" required>
|
|
517
|
-
<FormField name="name" label="Full Name" validation={{ required: true }} />
|
|
518
|
-
<FormField name="email" label="Email Address" type="email" validation={{ required: true }} />
|
|
519
|
-
<FormField name="age" label="Age" type="number" validation={{ required: true }} />
|
|
520
|
-
</FormFieldset>
|
|
521
|
-
<button type="submit">Submit</button>
|
|
522
|
-
</Form>
|
|
523
|
-
);
|
|
524
|
-
|
|
525
|
-
const submitButton = screen.getByRole('button', { name: 'Submit' });
|
|
526
|
-
await user.click(submitButton);
|
|
527
|
-
|
|
528
|
-
// 1. All fields empty: expect 3 'Required' errors
|
|
529
|
-
await waitFor(() => {
|
|
530
|
-
const requiredErrors = screen.getAllByText('Required');
|
|
531
|
-
expect(requiredErrors).toHaveLength(3);
|
|
532
|
-
requiredErrors.forEach((el) => {
|
|
533
|
-
expect(el).toHaveAttribute('role', 'alert');
|
|
534
|
-
});
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
// 2. Fill in invalid values for email and age, submit again
|
|
538
|
-
const emailInput = screen.getByRole('textbox', { name: /email/i });
|
|
539
|
-
const ageInput = screen.getByRole('spinbutton', { name: /age/i });
|
|
540
|
-
await user.clear(emailInput);
|
|
541
|
-
await user.type(emailInput, 'not-an-email');
|
|
542
|
-
await user.clear(ageInput);
|
|
543
|
-
await user.type(ageInput, '10');
|
|
544
|
-
await user.click(submitButton);
|
|
545
|
-
|
|
546
|
-
await waitFor(() => {
|
|
547
|
-
expect(screen.getByText('Invalid email format')).toBeInTheDocument();
|
|
548
|
-
expect(screen.getByText('Expected number, received string')).toBeInTheDocument();
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
// Check that error messages have proper ARIA attributes
|
|
552
|
-
const errorMessages = screen.getAllByRole('alert');
|
|
553
|
-
expect(errorMessages.length).toBeGreaterThan(0);
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
it('should support keyboard-only navigation', async () => {
|
|
557
|
-
renderWithProviders(
|
|
558
|
-
<Form onSubmit={() => {}}>
|
|
559
|
-
<FormFieldset legend="Contact Information">
|
|
560
|
-
<FormField name="name" label="Name" />
|
|
561
|
-
<FormField name="email" label="Email" type="email" />
|
|
562
|
-
</FormFieldset>
|
|
563
|
-
<button type="submit">Submit</button>
|
|
564
|
-
</Form>
|
|
565
|
-
);
|
|
566
|
-
|
|
567
|
-
const nameInput = screen.getByLabelText('Name');
|
|
568
|
-
const emailInput = screen.getByLabelText('Email');
|
|
569
|
-
const submitButton = screen.getByRole('button', { name: 'Submit' });
|
|
570
|
-
|
|
571
|
-
// Test tab navigation
|
|
572
|
-
await user.tab();
|
|
573
|
-
expect(nameInput).toHaveFocus();
|
|
574
|
-
|
|
575
|
-
await user.tab();
|
|
576
|
-
expect(emailInput).toHaveFocus();
|
|
577
|
-
|
|
578
|
-
await user.tab();
|
|
579
|
-
expect(submitButton).toHaveFocus();
|
|
580
|
-
|
|
581
|
-
// Test shift+tab for reverse navigation
|
|
582
|
-
await user.tab({ shift: true });
|
|
583
|
-
expect(emailInput).toHaveFocus();
|
|
584
|
-
});
|
|
585
|
-
|
|
586
|
-
it('should announce form state changes to screen readers', async () => {
|
|
587
|
-
const schema = z.object({
|
|
588
|
-
name: z.string().min(1, 'Name is required'),
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
const mockForm = {
|
|
592
|
-
formState: {
|
|
593
|
-
isSubmitting: true,
|
|
594
|
-
isSubmitSuccessful: false,
|
|
595
|
-
errors: {},
|
|
596
|
-
isValid: false,
|
|
597
|
-
isDirty: false,
|
|
598
|
-
touchedFields: {},
|
|
599
|
-
},
|
|
600
|
-
} as any;
|
|
601
|
-
|
|
602
|
-
renderWithProviders(
|
|
603
|
-
<Form schema={schema} onSubmit={() => {}}>
|
|
604
|
-
<FormLiveRegion form={mockForm} />
|
|
605
|
-
<FormField name="name" label="Name" />
|
|
606
|
-
<button type="submit">Submit</button>
|
|
607
|
-
</Form>
|
|
608
|
-
);
|
|
609
|
-
|
|
610
|
-
const liveRegion = screen.getByRole('status');
|
|
611
|
-
expect(liveRegion).toBeInTheDocument();
|
|
612
|
-
});
|
|
613
|
-
});
|
|
614
|
-
describe('Form Error Handling', () => {
|
|
615
|
-
const user = userEvent.setup();
|
|
616
|
-
let restoreConsole: (() => void) | null = null;
|
|
617
|
-
|
|
618
|
-
beforeEach(() => {
|
|
619
|
-
restoreConsole = errorTestingUtils.suppressConsoleErrors();
|
|
620
|
-
});
|
|
621
|
-
|
|
622
|
-
afterEach(() => {
|
|
623
|
-
if (restoreConsole) {
|
|
624
|
-
restoreConsole();
|
|
625
|
-
}
|
|
626
|
-
});
|
|
627
|
-
|
|
628
|
-
it('should handle component errors gracefully', () => {
|
|
629
|
-
const ErrorComponent = () => {
|
|
630
|
-
throw new Error('Form component error');
|
|
631
|
-
};
|
|
632
|
-
|
|
633
|
-
renderWithProviders(
|
|
634
|
-
<TestErrorBoundary>
|
|
635
|
-
<ErrorComponent />
|
|
636
|
-
</TestErrorBoundary>
|
|
637
|
-
);
|
|
638
|
-
|
|
639
|
-
expect(screen.getByTestId('error-boundary')).toBeInTheDocument();
|
|
640
|
-
expect(screen.getByText('Error: Form component error')).toBeInTheDocument();
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
it('should handle async errors', async () => {
|
|
644
|
-
const AsyncErrorComponent = ({ shouldFail }: { shouldFail: boolean }) => {
|
|
645
|
-
const [error, setError] = React.useState<Error | null>(null);
|
|
646
|
-
|
|
647
|
-
React.useEffect(() => {
|
|
648
|
-
if (shouldFail) {
|
|
649
|
-
setError(new Error('Async error'));
|
|
650
|
-
}
|
|
651
|
-
}, [shouldFail]);
|
|
652
|
-
|
|
653
|
-
if (error) {
|
|
654
|
-
throw error;
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
return <div>Async component</div>;
|
|
658
|
-
};
|
|
659
|
-
|
|
660
|
-
renderWithProviders(
|
|
661
|
-
<TestErrorBoundary>
|
|
662
|
-
<AsyncErrorComponent shouldFail={true} />
|
|
663
|
-
</TestErrorBoundary>
|
|
664
|
-
);
|
|
665
|
-
|
|
666
|
-
await waitFor(() => {
|
|
667
|
-
expect(screen.getByTestId('error-boundary')).toBeInTheDocument();
|
|
668
|
-
});
|
|
669
|
-
});
|
|
670
|
-
|
|
671
|
-
it('should handle user interaction errors', async () => {
|
|
672
|
-
const ErrorComponent = errorTestingUtils.createErrorThrowingComponent(
|
|
673
|
-
'Form interaction error',
|
|
674
|
-
'click'
|
|
675
|
-
);
|
|
676
|
-
|
|
677
|
-
renderWithProviders(
|
|
678
|
-
<TestErrorBoundary>
|
|
679
|
-
<ErrorComponent />
|
|
680
|
-
</TestErrorBoundary>
|
|
681
|
-
);
|
|
682
|
-
|
|
683
|
-
await user.click(screen.getByTestId('error-button'));
|
|
684
|
-
|
|
685
|
-
await waitFor(() => {
|
|
686
|
-
expect(screen.getByTestId('error-display')).toBeInTheDocument();
|
|
687
|
-
});
|
|
688
|
-
});
|
|
689
|
-
|
|
690
|
-
it('should recover from errors when props change', async () => {
|
|
691
|
-
const TestComponent = ({ shouldError }: { shouldError: boolean }) => {
|
|
692
|
-
if (shouldError) {
|
|
693
|
-
throw new Error('Form prop error');
|
|
694
|
-
}
|
|
695
|
-
return <div>Normal content</div>;
|
|
696
|
-
};
|
|
697
|
-
|
|
698
|
-
await errorTestingUtils.testErrorRecovery(
|
|
699
|
-
TestComponent,
|
|
700
|
-
{ shouldError: true },
|
|
701
|
-
{ shouldError: false }
|
|
702
|
-
);
|
|
703
|
-
|
|
704
|
-
expect(screen.getByText('Normal content')).toBeInTheDocument();
|
|
705
|
-
});
|
|
706
|
-
});
|
|
707
|
-
describe('Form Edge Cases', () => {
|
|
708
|
-
describe('Extreme Data Values', () => {
|
|
709
|
-
it('should handle very long strings', () => {
|
|
710
|
-
const longString = edgeCaseUtils.generateExtremeData.longString(1000);
|
|
711
|
-
|
|
712
|
-
const { container } = renderWithProviders(<Form>{longString}</Form>);
|
|
713
|
-
expect(container.querySelector('form')).toBeInTheDocument();
|
|
714
|
-
});
|
|
715
|
-
|
|
716
|
-
it('should handle empty and null values', () => {
|
|
717
|
-
const emptyValues = edgeCaseUtils.generateExtremeData.emptyValues();
|
|
718
|
-
|
|
719
|
-
emptyValues.forEach(value => {
|
|
720
|
-
const { container, unmount } = renderWithProviders(<Form>{value as any}</Form>);
|
|
721
|
-
expect(container.querySelector('form')).toBeInTheDocument();
|
|
722
|
-
unmount();
|
|
723
|
-
});
|
|
724
|
-
});
|
|
725
|
-
|
|
726
|
-
it('should handle special characters', () => {
|
|
727
|
-
const specialChars = edgeCaseUtils.generateExtremeData.specialChars();
|
|
728
|
-
|
|
729
|
-
const { container } = renderWithProviders(<Form>{specialChars}</Form>);
|
|
730
|
-
expect(container.querySelector('form')).toBeInTheDocument();
|
|
731
|
-
});
|
|
732
|
-
|
|
733
|
-
it('should handle unicode characters', () => {
|
|
734
|
-
const unicodeChars = edgeCaseUtils.generateExtremeData.unicodeChars();
|
|
735
|
-
|
|
736
|
-
const { container } = renderWithProviders(<Form>{unicodeChars}</Form>);
|
|
737
|
-
expect(container.querySelector('form')).toBeInTheDocument();
|
|
738
|
-
});
|
|
739
|
-
});
|
|
740
|
-
|
|
741
|
-
describe('Extreme Numbers', () => {
|
|
742
|
-
it('should handle very large numbers', () => {
|
|
743
|
-
const largeNumbers = edgeCaseUtils.generateExtremeData.largeNumbers();
|
|
744
|
-
|
|
745
|
-
largeNumbers.forEach(number => {
|
|
746
|
-
const { container, unmount } = renderWithProviders(<Form value={number} />);
|
|
747
|
-
expect(container.querySelector('form')).toBeInTheDocument();
|
|
748
|
-
unmount();
|
|
749
|
-
});
|
|
750
|
-
});
|
|
751
|
-
|
|
752
|
-
it('should handle very small numbers', () => {
|
|
753
|
-
const smallNumbers = edgeCaseUtils.generateExtremeData.smallNumbers();
|
|
754
|
-
|
|
755
|
-
smallNumbers.forEach(number => {
|
|
756
|
-
const { container, unmount } = renderWithProviders(<Form value={number} />);
|
|
757
|
-
expect(container.querySelector('form')).toBeInTheDocument();
|
|
758
|
-
unmount();
|
|
759
|
-
});
|
|
760
|
-
});
|
|
761
|
-
});
|
|
762
|
-
|
|
763
|
-
describe('Rapid State Changes', () => {
|
|
764
|
-
it('should handle rapid prop changes', async () => {
|
|
765
|
-
const stateProps = [
|
|
766
|
-
{ children: 'State 1' },
|
|
767
|
-
{ children: 'State 2' },
|
|
768
|
-
{ children: 'State 3' },
|
|
769
|
-
{ children: 'State 4' },
|
|
770
|
-
{ children: 'State 5' },
|
|
771
|
-
];
|
|
772
|
-
|
|
773
|
-
await edgeCaseUtils.testRapidStateChanges(Form, stateProps);
|
|
774
|
-
});
|
|
775
|
-
|
|
776
|
-
it('should handle rapid user interactions', async () => {
|
|
777
|
-
const { container } = renderWithProviders(<Form />);
|
|
778
|
-
|
|
779
|
-
// Form should render successfully
|
|
780
|
-
expect(container.querySelector('form')).toBeInTheDocument();
|
|
781
|
-
});
|
|
782
|
-
});
|
|
783
|
-
|
|
784
|
-
describe('Memory Management', () => {
|
|
785
|
-
it('should not leak memory with repeated renders', () => {
|
|
786
|
-
edgeCaseUtils.testMemoryLeaks(Form, { children: 'Memory test' });
|
|
787
|
-
});
|
|
788
|
-
});
|
|
789
|
-
|
|
790
|
-
describe('Boundary Conditions', () => {
|
|
791
|
-
it('should handle boundary prop values', () => {
|
|
792
|
-
const boundaryProps = [
|
|
793
|
-
{ children: '' },
|
|
794
|
-
{ children: 0 },
|
|
795
|
-
{ children: false },
|
|
796
|
-
{ children: [] },{ className: '' },
|
|
797
|
-
{ 'data-testid': '' },
|
|
798
|
-
];
|
|
799
|
-
|
|
800
|
-
edgeCaseUtils.testBoundaryConditions(Form, boundaryProps);
|
|
801
|
-
});
|
|
802
|
-
});
|
|
803
|
-
|
|
804
|
-
describe('Complex Data Structures', () => {
|
|
805
|
-
it('should handle deeply nested objects', () => {
|
|
806
|
-
const deepObject = edgeCaseUtils.generateExtremeData.deepObject(5);
|
|
807
|
-
|
|
808
|
-
const { container } = renderWithProviders(<Form data={deepObject} />);
|
|
809
|
-
expect(container.querySelector('form')).toBeInTheDocument();
|
|
810
|
-
});
|
|
811
|
-
|
|
812
|
-
it('should handle large arrays', () => {
|
|
813
|
-
const largeArray = edgeCaseUtils.generateExtremeData.largeArray(1000);
|
|
814
|
-
|
|
815
|
-
const { container } = renderWithProviders(<Form items={largeArray} />);
|
|
816
|
-
expect(container.querySelector('form')).toBeInTheDocument();
|
|
817
|
-
});
|
|
818
|
-
});
|
|
819
|
-
});
|
|
820
|
-
});
|