@jmruthers/pace-core 0.6.9 → 0.6.10
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/audit-tool/audits/02-project-structure.cjs +62 -0
- package/audit-tool/audits/03-architecture.cjs +145 -19
- package/audit-tool/audits/04-code-quality.cjs +86 -1
- package/audit-tool/audits/06-security-rbac.cjs +109 -11
- package/cursor-rules/02-project-structure.mdc +2 -26
- package/cursor-rules/05-styling.mdc +84 -6
- package/cursor-rules/06-security-rbac.mdc +124 -1
- package/dist/{DataTable-SOAFXIWY.js → DataTable-SAXFG4XI.js} +11 -13
- package/dist/{AuthService-DmfO5rGS.d.ts → InactivityServiceProvider-DHryoh6K.d.ts} +24 -249
- package/dist/UnifiedAuthProvider-BBD2PS3Q.js +7 -0
- package/dist/{UnifiedAuthProvider-CKvHP1MK.d.ts → UnifiedAuthProvider-CiBAl9-s.d.ts} +34 -22
- package/dist/{api-7P7DI652.js → api-F47QJ7FX.js} +3 -3
- package/dist/assets/app-icons/admin_favicon.svg +462 -0
- package/dist/assets/app-icons/base_favicon.svg +85 -0
- package/dist/assets/app-icons/cake_favicon.svg +68 -0
- package/dist/assets/app-icons/core_favicon.svg +256 -0
- package/dist/assets/app-icons/gear_favicon.svg +91 -0
- package/dist/assets/app-icons/medi_favicon.svg +92 -0
- package/dist/assets/app-icons/mint_favicon.svg +83 -0
- package/dist/assets/app-icons/pace_favicon.svg +49 -0
- package/dist/assets/app-icons/pump_favicon.svg +68 -0
- package/dist/assets/app-icons/seed_favicon.svg +91 -0
- package/dist/assets/app-icons/team_favicon.svg +67 -0
- package/dist/assets/app-icons/trac_favicon.svg +112 -0
- package/dist/assets/app-icons/trip_favicon.svg +102 -0
- package/dist/audit-Z6ZZBWLU.js +3 -0
- package/dist/chunk-3GWSPISD.js +61 -0
- package/dist/{chunk-4DDCYDQ3.js → chunk-66R6RLUZ.js} +12 -27
- package/dist/{chunk-FYHN4DD5.js → chunk-7YDC7LMU.js} +80 -8
- package/dist/{chunk-S7DKJPLT.js → chunk-BCTXBU6U.js} +22 -17
- package/dist/{chunk-TTRFSOKR.js → chunk-BTHN5MKC.js} +4 -4
- package/dist/{chunk-A3W6LW53.js → chunk-DDMPHZ3D.js} +6 -18
- package/dist/{chunk-MPBLMWVR.js → chunk-FBZ7U3ID.js} +140 -92
- package/dist/chunk-FN52B75D.js +246 -0
- package/dist/{chunk-5W2A3DRC.js → chunk-JJEYZ3DX.js} +5 -4
- package/dist/chunk-KPYQWGFQ.js +183 -0
- package/dist/{chunk-C7ZQ5O4C.js → chunk-KSNLMI7N.js} +3 -3
- package/dist/chunk-KYURMOQM.js +977 -0
- package/dist/{chunk-LX6U42O3.js → chunk-LNHFAF4X.js} +160 -58
- package/dist/{chunk-J2U36LHD.js → chunk-MPY44PWB.js} +620 -627
- package/dist/{chunk-AHU7G2R5.js → chunk-NIU6DPQV.js} +10 -6
- package/dist/{chunk-HF6O3O37.js → chunk-RMLY6KB5.js} +1 -1
- package/dist/{chunk-6GLLNA6U.js → chunk-SACF5YSM.js} +1 -1
- package/dist/{chunk-5HNSDQWH.js → chunk-TFIPNIPE.js} +865 -532
- package/dist/{chunk-OJ4SKRSV.js → chunk-UZNAFKGW.js} +25 -5
- package/dist/chunk-W46INAVW.js +1216 -0
- package/dist/chunk-X5EAU5G7.js +793 -0
- package/dist/{chunk-T5CVK4R3.js → chunk-Y4PF6HIM.js} +110 -64
- package/dist/components.d.ts +8 -86
- package/dist/components.js +21 -55
- package/dist/eslint-rules/rules/05-styling.cjs +507 -0
- package/dist/eslint-rules/rules/06-security-rbac.cjs +10 -0
- package/dist/{event-CW5YB_2p.d.ts → event-WTAQuGcq.d.ts} +1 -1
- package/dist/{functions-lBy5L2ry.d.ts → functions-DH45k8ec.d.ts} +1 -1
- package/dist/hooks.d.ts +11 -10
- package/dist/hooks.js +69 -44
- package/dist/index.d.ts +379 -31
- package/dist/index.js +46 -32
- package/dist/papaparseLoader-WG2UXQ22.js +7 -0
- package/dist/providers.d.ts +28 -14
- package/dist/providers.js +5 -5
- package/dist/rbac/eslint-rules.js +2 -2
- package/dist/rbac/index.d.ts +57 -213
- package/dist/rbac/index.js +11 -11
- package/dist/theming/runtime.d.ts +9 -3
- package/dist/theming/runtime.js +2 -2
- package/dist/{timezone-0AyangqX.d.ts → timezone-K-ptz3HO.d.ts} +21 -22
- package/dist/{types-t9H8qKRw.d.ts → types-BE2sEHKd.d.ts} +1 -1
- package/dist/{types-BeoeWV5I.d.ts → types-CvOPXWWZ.d.ts} +6 -5
- package/dist/{types-DXstZpNI.d.ts → types-D05dCGma.d.ts} +56 -149
- package/dist/types-Dr8sNhER.d.ts +50 -0
- package/dist/types.d.ts +4 -4
- package/dist/{PublicPageProvider-CIGSujI2.d.ts → usePublicPageContext-vxBlEHO9.d.ts} +294 -151
- package/dist/{usePublicRouteParams-DQLrDqDb.d.ts → usePublicRouteParams-G3Ks53mk.d.ts} +7 -6
- package/dist/utils.d.ts +300 -136
- package/dist/utils.js +42 -41
- package/dist/{validation-643vUDZW.d.ts → validation-g5n0hDkh.d.ts} +2 -2
- package/docs/api/modules.md +542 -549
- package/docs/api-reference/components.md +5 -5
- package/docs/implementation-guides/data-tables.md +190 -8
- package/docs/rbac/RBAC_CONTRACT.md +0 -12
- package/docs/standards/2-project-structure-standards.md +12 -74
- package/docs/standards/6-security-rbac-standards.md +222 -7
- package/docs/standards/7-api-tech-stack-standards.md +91 -3
- package/docs/testing/README.md +10 -0
- package/docs/testing/test-setup-for-consumers.md +914 -0
- package/eslint-config-pace-core.cjs +4 -0
- package/package.json +1 -1
- package/scripts/eslint-audit.cjs +110 -11
- package/src/__mocks__/lucide-react.ts +0 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -2
- package/src/__tests__/index.test.ts +532 -0
- package/src/__tests__/integration/UserProfile.test.tsx +1 -1
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +10 -8
- package/src/__tests__/rls-policies.test.ts +3 -2
- package/src/assets/app-icons/admin_favicon.svg +462 -0
- package/src/assets/app-icons/base_favicon.svg +85 -0
- package/src/assets/app-icons/cake_favicon.svg +68 -0
- package/src/assets/app-icons/core_favicon.svg +256 -0
- package/src/assets/app-icons/gear_favicon.svg +91 -0
- package/src/assets/app-icons/index.ts +83 -0
- package/src/assets/app-icons/medi_favicon.svg +92 -0
- package/src/assets/app-icons/mint_favicon.svg +83 -0
- package/src/assets/app-icons/pace_favicon.svg +49 -0
- package/src/assets/app-icons/pump_favicon.svg +68 -0
- package/src/assets/app-icons/seed_favicon.svg +91 -0
- package/src/assets/app-icons/team_favicon.svg +67 -0
- package/src/assets/app-icons/trac_favicon.svg +112 -0
- package/src/assets/app-icons/trip_favicon.svg +102 -0
- package/src/components/AddressField/AddressField.test.tsx +378 -3
- package/src/components/AddressField/AddressField.tsx +2 -2
- package/src/components/AddressField/types.ts +2 -2
- package/src/components/Alert/Alert.test.tsx +35 -25
- package/src/components/Alert/Alert.tsx +8 -8
- package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
- package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
- package/src/components/Avatar/Avatar.test.tsx +11 -1
- package/src/components/Avatar/Avatar.tsx +3 -2
- package/src/components/Badge/Badge.test.tsx +11 -1
- package/src/components/Button/Button.test.tsx +13 -3
- package/src/components/Calendar/Calendar.test.tsx +523 -131
- package/src/components/Calendar/Calendar.tsx +107 -488
- package/src/components/Card/Card.test.tsx +220 -249
- package/src/components/Checkbox/Checkbox.test.tsx +58 -174
- package/src/components/ContextSelector/ContextSelector.tsx +3 -3
- package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +360 -0
- package/src/components/DataTable/DataTable.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -1
- package/src/components/DataTable/__tests__/DataTable.export.test.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +1 -1
- package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +16 -14
- package/src/components/DataTable/__tests__/DataTable.test.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +1 -1
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +76 -580
- package/src/components/DataTable/__tests__/README.md +1 -1
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +1 -1
- package/src/components/DataTable/__tests__/keyboard.test.tsx +1 -1
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +1 -3
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -6
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +14 -6
- package/src/components/DataTable/components/ActionButtons.tsx +9 -4
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +3 -3
- package/src/components/DataTable/components/ColumnFilter.tsx +2 -7
- package/src/components/DataTable/components/DataTableCore.tsx +44 -52
- package/src/components/DataTable/components/DataTableLayout.tsx +37 -26
- package/src/components/DataTable/components/DataTableModals.tsx +118 -30
- package/src/components/DataTable/components/DataTableToolbar.tsx +2 -2
- package/src/components/DataTable/components/EditFields.tsx +6 -47
- package/src/components/DataTable/components/EditableRow.tsx +8 -8
- package/src/components/DataTable/components/EmptyState.tsx +6 -3
- package/src/components/DataTable/components/FilterRow.tsx +18 -11
- package/src/components/DataTable/components/GroupingDropdown.tsx +0 -1
- package/src/components/DataTable/components/ImportModal.tsx +305 -133
- package/src/components/DataTable/components/LoadingState.tsx +2 -2
- package/src/components/DataTable/components/PaginationControls.tsx +0 -4
- package/src/components/DataTable/components/RowComponent.tsx +42 -22
- package/src/components/DataTable/components/UnifiedTableBody.tsx +52 -12
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +51 -463
- package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +122 -116
- package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +40 -68
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +9 -137
- package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +57 -17
- package/src/components/DataTable/components/__tests__/DataTableCore.test.tsx +792 -0
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +24 -65
- package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +467 -0
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +8 -125
- package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +528 -56
- package/src/components/DataTable/components/__tests__/EditFields.test.tsx +526 -0
- package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +1 -68
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +8 -25
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +3 -62
- package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +9 -14
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +50 -186
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +39 -97
- package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +13 -103
- package/src/components/DataTable/components/__tests__/RowComponent.test.tsx +629 -0
- package/src/components/DataTable/components/__tests__/SortIndicator.test.tsx +135 -0
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +31 -171
- package/src/components/DataTable/components/__tests__/cellValueUtils.test.ts +453 -0
- package/src/components/DataTable/components/hooks/useImportModalFocus.test.ts +184 -0
- package/src/components/DataTable/components/hooks/usePermissionTracking.test.ts +381 -0
- package/src/components/DataTable/context/DataTableContext.tsx +9 -10
- package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +12 -26
- package/src/components/DataTable/core/ColumnFactory.ts +3 -3
- package/src/components/DataTable/core/ColumnManager.ts +0 -1
- package/src/components/DataTable/core/DataManager.ts +4 -2
- package/src/components/DataTable/core/LocalDataAdapter.ts +1 -1
- package/src/components/DataTable/core/PluginRegistry.ts +2 -2
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +114 -2
- package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +103 -5
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +57 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +63 -0
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +42 -9
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +29 -7
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +58 -4
- package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +16 -21
- package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +93 -4
- package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +227 -54
- package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +215 -62
- package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +217 -39
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +101 -6
- package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +157 -27
- package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +80 -0
- package/src/components/DataTable/hooks/__tests__/useKeyboardNavigation.test.ts +787 -0
- package/src/components/DataTable/hooks/__tests__/useServerSideDataEffect.test.ts +258 -0
- package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +128 -77
- package/src/components/DataTable/hooks/__tests__/useTableHandlers.test.ts +440 -0
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
- package/src/components/DataTable/hooks/useDataTableConfiguration.ts +1 -1
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +11 -22
- package/src/components/DataTable/hooks/useDataTableState.ts +20 -24
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +5 -5
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +13 -1
- package/src/components/DataTable/hooks/useTableColumns.ts +15 -39
- package/src/components/DataTable/hooks/useTableHandlers.ts +8 -20
- package/src/components/DataTable/index.ts +24 -2
- package/src/components/DataTable/types.ts +6 -3
- package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +3 -67
- package/src/components/DataTable/utils/__tests__/aggregationUtils.test.ts +288 -0
- package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +3 -60
- package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +1 -1
- package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +9 -21
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +102 -86
- package/src/components/DataTable/utils/__tests__/paginationUtils.test.ts +593 -0
- package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +33 -49
- package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +1 -0
- package/src/components/DataTable/utils/a11yUtils.ts +1 -1
- package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
- package/src/components/DataTable/utils/errorHandling.ts +3 -1
- package/src/components/DataTable/utils/exportUtils.ts +1 -1
- package/src/components/DataTable/utils/flexibleImport.ts +2 -2
- package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
- package/src/components/DataTable/utils/paginationUtils.ts +1 -1
- package/src/components/DataTable/utils/performanceUtils.ts +1 -1
- package/src/components/DataTable/utils/selectFieldUtils.ts +0 -7
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +17 -24
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
- package/src/components/DateTimeField/DateTimeField.test.tsx +2 -15
- package/src/components/DateTimeField/DateTimeField.tsx +1 -1
- package/src/components/Dialog/Dialog.test.tsx +2007 -407
- package/src/components/Dialog/Dialog.tsx +97 -192
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
- package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
- package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
- package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
- package/src/components/ErrorBoundary/index.ts +3 -4
- package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
- package/src/components/FileDisplay/FileDisplay.test.tsx +454 -222
- package/src/components/FileDisplay/FileDisplay.tsx +14 -12
- package/src/components/FileDisplay/index.tsx +1 -1
- package/src/components/FileUpload/FileUpload.test.tsx +54 -18
- package/src/components/FileUpload/FileUpload.tsx +10 -7
- package/src/components/FileUpload/index.tsx +1 -1
- package/src/components/Footer/Footer.test.tsx +33 -114
- package/src/components/Form/Form.test.tsx +388 -68
- package/src/components/Form/Form.tsx +57 -42
- package/src/components/Header/Header.test.tsx +645 -154
- package/src/components/Header/Header.tsx +52 -43
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
- package/src/components/Input/Input.test.tsx +34 -120
- package/src/components/Label/Label.test.tsx +47 -46
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +9 -12
- package/src/components/LoginForm/LoginForm.test.tsx +0 -1
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +1399 -82
- package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
- package/src/components/NavigationMenu/__tests__/useNavigationFiltering.test.ts +1934 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +5 -15
- package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1307 -0
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +47 -46
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +87 -66
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +245 -39
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -20
- package/src/components/PaceAppLayout/README.md +0 -9
- package/src/components/PaceAppLayout/test-setup.tsx +15 -9
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +759 -3
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +2 -3
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
- package/src/components/Progress/Progress.test.tsx +127 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +24 -6
- package/src/components/PublicLayout/PublicLayout.test.tsx +1435 -14
- package/src/components/PublicLayout/PublicPageContext.ts +28 -0
- package/src/components/PublicLayout/PublicPageLayout.tsx +6 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +2 -41
- package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
- package/src/components/Select/Select.test.tsx +46 -9
- package/src/components/Select/Select.tsx +31 -24
- package/src/components/Select/__tests__/context.test.tsx +56 -0
- package/src/components/Select/hooks/__tests__/useSelectEvents.test.ts +279 -0
- package/src/components/Select/hooks/__tests__/useSelectSearch.test.tsx +295 -0
- package/src/components/Select/hooks/__tests__/useSelectState.test.ts +254 -0
- package/src/components/Select/hooks/useSelectState.ts +16 -16
- package/src/components/Select/types.ts +3 -0
- package/src/components/Select/utils/__tests__/text.test.tsx +104 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
- package/src/components/Switch/Switch.test.tsx +57 -153
- package/src/components/Table/Table.test.tsx +47 -317
- package/src/components/Tabs/Tabs.tsx +3 -3
- package/src/components/Textarea/Textarea.test.tsx +11 -38
- package/src/components/Toast/Toast.test.tsx +78 -569
- package/src/components/Tooltip/Tooltip.test.tsx +4 -21
- package/src/components/UserMenu/UserMenu.test.tsx +1 -21
- package/src/components/UserMenu/UserMenu.tsx +0 -1
- package/src/components/__tests__/index.test.ts +346 -0
- package/src/components/index.ts +12 -1
- package/src/constants/__tests__/performance.test.ts +91 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +239 -129
- package/src/hooks/__tests__/hooks.integration.test.tsx +4 -3
- package/src/hooks/__tests__/useApiFetch.unit.test.ts +1 -1
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +88 -29
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +282 -98
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +53 -109
- package/src/hooks/__tests__/useDataTableState.test.ts +143 -49
- package/src/hooks/__tests__/useDebounce.unit.test.ts +94 -19
- package/src/hooks/__tests__/useEvents.unit.test.ts +100 -125
- package/src/hooks/__tests__/useFileDisplay.test.ts +540 -0
- package/src/hooks/__tests__/useFileDisplay.unit.test.ts +1 -4
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +27 -247
- package/src/hooks/__tests__/useFileUrlCache.test.ts +246 -56
- package/src/hooks/__tests__/useFocusManagement.unit.test.ts +442 -68
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +345 -560
- package/src/hooks/__tests__/useFormDialog.test.ts +51 -222
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +1 -1
- package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +1 -4
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -1
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +1 -1
- package/src/hooks/__tests__/usePermissionCache.test.ts +506 -0
- package/src/hooks/__tests__/usePreventTabReload.test.ts +255 -36
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +17 -8
- package/src/hooks/__tests__/usePublicEvent.test.ts +16 -24
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +12 -4
- package/src/hooks/__tests__/usePublicFileDisplay.test.ts +3 -6
- package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +1 -2
- package/src/hooks/__tests__/useQueryCache.test.ts +313 -66
- package/src/hooks/__tests__/useSessionDraft.test.ts +496 -103
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +2 -2
- package/src/hooks/__tests__/useStorage.unit.test.ts +72 -102
- package/src/hooks/__tests__/useToast.test.ts +413 -0
- package/src/hooks/__tests__/useToast.unit.test.tsx +1 -1
- package/src/hooks/__tests__/useZodForm.unit.test.tsx +175 -21
- package/src/hooks/index.ts +13 -1
- package/src/hooks/public/usePublicEvent.test.ts +304 -0
- package/src/hooks/public/usePublicEvent.ts +11 -11
- package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
- package/src/hooks/public/usePublicEventLogo.ts +2 -2
- package/src/hooks/public/usePublicFileDisplay.test.ts +723 -0
- package/src/hooks/public/usePublicFileDisplay.ts +79 -49
- package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
- package/src/hooks/public/usePublicRouteParams.ts +2 -2
- package/src/hooks/services/useAuthService.ts +1 -1
- package/src/hooks/services/useEventService.ts +1 -1
- package/src/hooks/useAccessibleApps.test.ts +400 -0
- package/src/hooks/useAccessibleApps.ts +264 -0
- package/src/hooks/useAddressAutocomplete.test.ts +165 -42
- package/src/hooks/useAddressAutocomplete.ts +41 -28
- package/src/hooks/useAppConfig.ts +13 -3
- package/src/hooks/useDataTablePerformance.ts +13 -12
- package/src/hooks/useDataTableState.ts +5 -5
- package/src/hooks/useEventTheme.test.ts +66 -17
- package/src/hooks/useEventTheme.ts +1 -1
- package/src/hooks/useEvents.ts +8 -1
- package/src/hooks/useFileDisplay.ts +66 -33
- package/src/hooks/useFileReference.test.ts +365 -87
- package/src/hooks/useFileReference.ts +2 -6
- package/src/hooks/useFileUrlCache.ts +4 -1
- package/src/hooks/useFormDialog.ts +2 -2
- package/src/hooks/useInactivityTracker.ts +3 -3
- package/src/hooks/useOrganisationPermissions.test.ts +1 -2
- package/src/hooks/useOrganisationPermissions.ts +1 -4
- package/src/hooks/useOrganisationSecurity.test.ts +1 -30
- package/src/hooks/useOrganisationSecurity.ts +3 -3
- package/src/hooks/useOrganisations.ts +1 -1
- package/src/hooks/usePerformanceMonitor.ts +1 -1
- package/src/hooks/usePermissionCache.ts +2 -6
- package/src/hooks/useQueryCache.ts +7 -7
- package/src/hooks/useSessionDraft.ts +14 -11
- package/src/hooks/useSessionRestoration.ts +1 -1
- package/src/hooks/useStorage.ts +75 -40
- package/src/hooks/useToast.ts +2 -2
- package/src/hooks/useZodForm.ts +3 -3
- package/src/icons/__tests__/index.test.ts +133 -0
- package/src/icons/index.ts +1 -1
- package/src/index.ts +43 -4
- package/src/providers/OrganisationProvider.test.tsx +40 -0
- package/src/providers/OrganisationProvider.tsx +5 -5
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
- package/src/providers/__tests__/AuthProvider.test.tsx +22 -91
- package/src/providers/__tests__/EventProvider.test.tsx +16 -80
- package/src/providers/__tests__/InactivityProvider.test.tsx +29 -173
- package/src/providers/__tests__/OrganisationProvider.test.tsx +4 -5
- package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +591 -0
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +80 -196
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +40 -133
- package/src/providers/__tests__/index.test.ts +138 -0
- package/src/providers/services/AuthServiceContext.ts +27 -0
- package/src/providers/services/AuthServiceProvider.tsx +81 -20
- package/src/providers/services/EventServiceContext.ts +25 -0
- package/src/providers/services/EventServiceProvider.tsx +11 -20
- package/src/providers/services/InactivityServiceContext.ts +25 -0
- package/src/providers/services/InactivityServiceProvider.tsx +7 -17
- package/src/providers/services/OrganisationServiceContext.ts +25 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
- package/src/providers/services/UnifiedAuthContext.ts +99 -0
- package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +38 -143
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +61 -95
- package/src/providers/services/__tests__/AuthServiceProvider.test.tsx +638 -0
- package/src/providers/services/__tests__/EventServiceProvider.test.tsx +839 -0
- package/src/providers/services/__tests__/InactivityServiceProvider.test.tsx +662 -0
- package/src/providers/services/__tests__/OrganisationServiceProvider.test.tsx +440 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.advanced.test.tsx +435 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.appId.test.tsx +408 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +55 -48
- package/src/providers/services/__tests__/contexts.test.tsx +281 -0
- package/src/providers/services/__tests__/useUnifiedAuth.test.tsx +251 -0
- package/src/providers/services/useUnifiedAuth.ts +29 -0
- package/src/rbac/README.md +5 -5
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +9 -14
- package/src/rbac/__tests__/audit-batched.test.ts +550 -0
- package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +1 -14
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +43 -12
- package/src/rbac/__tests__/cache-invalidation.test.ts +8 -14
- package/src/rbac/__tests__/engine.comprehensive.test.ts +2 -7
- package/src/rbac/__tests__/index.test.ts +107 -0
- package/src/rbac/__tests__/performance.test.ts +451 -0
- package/src/rbac/__tests__/rbac-core.test.tsx +2 -2
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -5
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +1 -7
- package/src/rbac/__tests__/rbac-functions.test.ts +0 -1
- package/src/rbac/__tests__/rbac-integration.test.ts +0 -1
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +21 -32
- package/src/rbac/adapters.test.tsx +654 -0
- package/src/rbac/adapters.tsx +24 -9
- package/src/rbac/api.test.ts +13 -217
- package/src/rbac/api.ts +85 -16
- package/src/rbac/audit-batched.ts +5 -4
- package/src/rbac/audit.test.ts +225 -28
- package/src/rbac/audit.ts +22 -17
- package/src/rbac/cache-invalidation.ts +18 -15
- package/src/rbac/cache.test.ts +123 -63
- package/src/rbac/cache.ts +3 -4
- package/src/rbac/components/AccessDenied.tsx +20 -18
- package/src/rbac/components/NavigationGuard.tsx +10 -8
- package/src/rbac/components/PagePermissionGuard.tsx +27 -25
- package/src/rbac/components/__tests__/AccessDenied.test.tsx +324 -0
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +242 -71
- package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +20 -37
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +18 -17
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +452 -129
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -13
- package/src/rbac/config.test.ts +131 -48
- package/src/rbac/config.ts +11 -8
- package/src/rbac/docs/event-based-apps.md +26 -13
- package/src/rbac/engine.test.ts +496 -146
- package/src/rbac/engine.ts +53 -13
- package/src/rbac/errors.test.ts +99 -87
- package/src/rbac/eslint-rules.js +2 -2
- package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -5
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +601 -1
- package/src/rbac/hooks/permissions/__tests__/useAccessLevel.test.ts +622 -0
- package/src/rbac/hooks/permissions/__tests__/useCan.test.ts +798 -0
- package/src/rbac/hooks/permissions/__tests__/useMultiplePermissions.test.ts +843 -0
- package/src/rbac/hooks/permissions/__tests__/usePermissions.test.ts +545 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +7 -8
- package/src/rbac/hooks/permissions/useCan.ts +12 -10
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +57 -8
- package/src/rbac/hooks/permissions/usePermissions.ts +15 -14
- package/src/rbac/hooks/useCan.test.ts +319 -3
- package/src/rbac/hooks/usePermissions.test.ts +426 -0
- package/src/rbac/hooks/usePermissions.ts +5 -7
- package/src/rbac/hooks/useRBAC.test.ts +1669 -2
- package/src/rbac/hooks/useRBAC.ts +7 -11
- package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
- package/src/rbac/hooks/useResolvedScope.ts +4 -1
- package/src/rbac/hooks/useResourcePermissions.test.ts +538 -1
- package/src/rbac/hooks/useResourcePermissions.ts +9 -7
- package/src/rbac/hooks/useRoleManagement.test.ts +659 -1
- package/src/rbac/hooks/useRoleManagement.ts +16 -12
- package/src/rbac/hooks/useSecureSupabase.ts +11 -12
- package/src/rbac/index.ts +32 -32
- package/src/rbac/permissions.test.ts +149 -68
- package/src/rbac/permissions.ts +0 -3
- package/src/rbac/request-deduplication.test.ts +347 -0
- package/src/rbac/secureClient.test.ts +112 -159
- package/src/rbac/secureClient.ts +46 -26
- package/src/rbac/security.test.ts +125 -44
- package/src/rbac/security.ts +7 -6
- package/src/rbac/types.test.ts +236 -0
- package/src/rbac/types.ts +7 -5
- package/src/rbac/utils/__tests__/clientSecurity.test.ts +192 -0
- package/src/rbac/utils/__tests__/contextValidator.test.ts +1 -3
- package/src/rbac/utils/__tests__/deep-equal.test.ts +23 -0
- package/src/rbac/utils/__tests__/eventContext.test.ts +10 -57
- package/src/rbac/utils/clientSecurity.ts +6 -4
- package/src/rbac/utils/contextValidator.ts +1 -2
- package/src/rbac/utils/eventContext.ts +2 -2
- package/src/services/AuthService.ts +13 -11
- package/src/services/EventService.ts +4 -5
- package/src/services/OrganisationService.ts +13 -30
- package/src/services/__tests__/AuthService.edge-cases.test.ts +746 -0
- package/src/services/__tests__/AuthService.restoreSession.test.ts +23 -3
- package/src/services/__tests__/AuthService.test.ts +4 -8
- package/src/services/__tests__/BaseService.edge-cases.test.ts +506 -0
- package/src/services/__tests__/BaseService.test.ts +49 -0
- package/src/services/__tests__/EventService.edge-cases.test.ts +633 -0
- package/src/services/__tests__/EventService.eventColours.test.ts +0 -12
- package/src/services/__tests__/EventService.test.ts +0 -7
- package/src/services/__tests__/InactivityService.edge-cases.test.ts +492 -0
- package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -5
- package/src/services/__tests__/OrganisationService.edge-cases.test.ts +633 -0
- package/src/services/base/BaseService.test.ts +214 -0
- package/src/services/interfaces/IOrganisationService.ts +0 -1
- package/src/services/interfaces/__tests__/IAuthService.test.ts +190 -0
- package/src/services/interfaces/__tests__/IEventService.test.ts +176 -0
- package/src/services/interfaces/__tests__/IInactivityService.test.ts +183 -0
- package/src/services/interfaces/__tests__/IOrganisationService.test.ts +207 -0
- package/src/styles/core.css +1 -0
- package/src/theming/__tests__/runtime.test.ts +29 -94
- package/src/theming/parseEventColours.ts +18 -9
- package/src/theming/runtime.ts +1 -5
- package/src/types/__tests__/core.test.ts +397 -0
- package/src/types/__tests__/database-generated.test.ts +78 -0
- package/src/types/__tests__/file-reference.test.ts +270 -366
- package/src/types/__tests__/guards.test.ts +26 -26
- package/src/types/__tests__/index.test.ts +265 -0
- package/src/types/__tests__/type-validation.test.ts +3 -3
- package/src/types/__tests__/validation.test.ts +0 -2
- package/src/types/auth.ts +0 -1
- package/src/types/event.ts +1 -1
- package/src/types/rpc-responses.ts +33 -0
- package/src/types/supabase.ts +1 -2
- package/src/types/vitest-globals.d.ts +1 -1
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +64 -77
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +13 -0
- package/src/utils/__tests__/formatDate.unit.test.ts +1 -1
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -1
- package/src/utils/__tests__/logger.unit.test.ts +1 -1
- package/src/utils/__tests__/performanceBenchmark.test.ts +1 -2
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +48 -13
- package/src/utils/__tests__/request-deduplication.test.ts +349 -0
- package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -1
- package/src/utils/__tests__/timezone.test.ts +1 -1
- package/src/utils/__tests__/validation.unit.test.ts +1 -2
- package/src/utils/__tests__/validationUtils.unit.test.ts +1 -1
- package/src/utils/app/appConfig.test.ts +235 -0
- package/src/utils/app/appIdResolver.test.ts +188 -20
- package/src/utils/app/appNameResolver.test.ts +18 -10
- package/src/utils/app/appNameResolver.ts +11 -9
- package/src/utils/app/appPortMap.test.ts +125 -0
- package/src/utils/app/appPortMap.ts +51 -0
- package/src/utils/app/buildAppUrl.test.ts +273 -0
- package/src/utils/app/buildAppUrl.ts +114 -0
- package/src/utils/audit/audit.test.ts +354 -39
- package/src/utils/context/organisationContext.test.ts +10 -4
- package/src/utils/context/organisationContext.ts +5 -5
- package/src/utils/context/sessionTracking.test.ts +354 -0
- package/src/utils/core/__tests__/cn.test.ts +66 -0
- package/src/utils/core/__tests__/debugLogger.test.ts +113 -0
- package/src/utils/core/__tests__/logger.test.ts +217 -0
- package/src/utils/core/debugLogger.ts +15 -8
- package/src/utils/core/logger.ts +20 -16
- package/src/utils/device/deviceFingerprint.test.ts +8 -5
- package/src/utils/device/deviceFingerprint.ts +3 -3
- package/src/utils/dynamic/__tests__/dynamicUtils.test.ts +185 -0
- package/src/utils/dynamic/__tests__/lazyLoad.test.tsx +156 -0
- package/src/utils/dynamic/createLazyComponent.tsx +38 -0
- package/src/utils/dynamic/dynamicUtils.ts +6 -6
- package/src/utils/dynamic/lazyLoad.tsx +8 -36
- package/src/utils/dynamic/papaparseLoader.ts +7 -0
- package/src/utils/file-reference/__tests__/file-reference.test.ts +583 -145
- package/src/utils/file-reference/index.ts +0 -1
- package/src/utils/formatting/formatDate.test.ts +22 -148
- package/src/utils/formatting/formatDateTime.test.ts +41 -119
- package/src/utils/formatting/formatDateTimeTimezone.test.ts +40 -84
- package/src/utils/formatting/formatNumber.test.ts +259 -0
- package/src/utils/formatting/formatTime.test.ts +36 -128
- package/src/utils/formatting/formatting.ts +1 -1
- package/src/utils/google-places/googlePlacesUtils.test.ts +72 -3
- package/src/utils/google-places/googlePlacesUtils.ts +15 -2
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +58 -1
- package/src/utils/google-places/loadGoogleMapsScript.ts +2 -1
- package/src/utils/index.ts +52 -11
- package/src/utils/location/location.test.ts +18 -115
- package/src/utils/performance/__tests__/bundleAnalysis.test.ts +148 -0
- package/src/utils/performance/__tests__/performanceBenchmark.test.ts +251 -0
- package/src/utils/performance/__tests__/performanceBudgets.test.ts +241 -0
- package/src/utils/performance/bundleAnalysis.ts +16 -22
- package/src/utils/performance/performanceBenchmark.ts +12 -4
- package/src/utils/performance/performanceBudgets.ts +9 -6
- package/src/utils/permissions/__tests__/permissionTypes.test.ts +149 -0
- package/src/utils/permissions/permissionUtils.test.ts +20 -42
- package/src/utils/persistence/__tests__/keyDerivation.test.ts +180 -9
- package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +164 -16
- package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
- package/src/utils/request-deduplication.ts +6 -4
- package/src/utils/security/auth-utils.ts +7 -7
- package/src/utils/security/secureDataAccess.test.ts +22 -191
- package/src/utils/security/secureErrors.test.ts +163 -0
- package/src/utils/security/secureStorage.test.ts +156 -0
- package/src/utils/security/secureStorage.ts +1 -1
- package/src/utils/security/security.test.ts +204 -0
- package/src/utils/security/securityMonitor.test.ts +90 -0
- package/src/utils/security/securityMonitor.ts +1 -1
- package/src/utils/storage/__tests__/config.unit.test.ts +239 -0
- package/src/utils/storage/__tests__/index.unit.test.ts +64 -12
- package/src/utils/storage/helpers.test.ts +757 -430
- package/src/utils/storage/helpers.ts +1 -2
- package/src/utils/storage/{index.ts → storageUtils.ts} +1 -36
- package/src/utils/storage/types.ts +2 -2
- package/src/utils/supabase/createBaseClient.test.ts +201 -0
- package/src/utils/supabase/createBaseClient.ts +2 -1
- package/src/utils/timezone/timezone.test.ts +25 -43
- package/src/utils/validation/__tests__/common.test.ts +115 -0
- package/src/utils/validation/__tests__/csrf.test.ts +65 -0
- package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +27 -7
- package/src/utils/validation/__tests__/passwordSchema.test.ts +164 -0
- package/src/utils/validation/__tests__/schema.test.ts +127 -0
- package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +76 -3
- package/src/utils/validation/__tests__/user.test.ts +173 -0
- package/src/utils/validation/__tests__/validation.test.ts +197 -0
- package/src/utils/validation/__tests__/validationUtils.test.ts +265 -43
- package/src/utils/validation/htmlSanitization.ts +27 -31
- package/src/utils/validation/schema.ts +6 -3
- package/src/utils/validation/sqlInjectionProtection.ts +2 -2
- package/src/vite-env.d.ts +6 -0
- package/dist/DataTable-DRUIgtUH.d.ts +0 -166
- package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
- package/dist/audit-MYQXYZFU.js +0 -3
- package/dist/chunk-7ILTDCL2.js +0 -80
- package/dist/chunk-EF2UGZWY.js +0 -611
- package/dist/chunk-FEJLJNWA.js +0 -181
- package/dist/chunk-GS5672WG.js +0 -2003
- package/dist/chunk-S6ZQKDY6.js +0 -62
- package/dist/chunk-Z2FNRKF3.js +0 -994
- package/dist/useToast-AyaT-x7p.d.ts +0 -68
- package/src/components/DataTable/components/index.ts +0 -16
- package/src/components/DataTable/core/index.ts +0 -1
- package/src/components/DataTable/hooks/index.ts +0 -13
- package/src/components/DataTable/utils/index.ts +0 -10
- package/src/components/PublicLayout/index.ts +0 -32
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
- package/src/hooks/public/index.ts +0 -36
- package/src/hooks/usePermissionCache.test.ts +0 -536
- package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
- package/src/rbac/audit-enhanced.ts +0 -384
- package/src/rbac/compliance/database-validator.ts +0 -165
- package/src/rbac/compliance/index.ts +0 -48
- package/src/rbac/compliance/pattern-detector.ts +0 -553
- package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
- package/src/rbac/compliance/runtime-compliance.ts +0 -99
- package/src/rbac/compliance/setup-validator.ts +0 -131
- package/src/rbac/components/index.ts +0 -26
- package/src/rbac/hooks/index.ts +0 -34
- package/src/rbac/hooks/permissions/index.ts +0 -4
- package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
- package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
- package/src/utils/app/appNameResolver.simple.test.ts +0 -212
- package/src/utils/google-places/index.ts +0 -26
- package/src/utils/location/index.ts +0 -16
- package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
- package/src/utils/timezone/index.ts +0 -17
- package/src/utils/validation/index.ts +0 -73
|
@@ -5,15 +5,14 @@
|
|
|
5
5
|
* @since 0.1.0
|
|
6
6
|
*
|
|
7
7
|
* A comprehensive header component for application layouts with navigation,
|
|
8
|
-
* user menu,
|
|
8
|
+
* user menu, context selector, and customizable branding.
|
|
9
9
|
*
|
|
10
10
|
* Features:
|
|
11
|
-
* - Customizable logo
|
|
11
|
+
* - Customizable logo via URL
|
|
12
12
|
* - Clickable logo that routes to dashboard (configurable)
|
|
13
13
|
* - Navigation menu integration
|
|
14
14
|
* - User menu with authentication
|
|
15
|
-
* -
|
|
16
|
-
* - Event selector for multi-tenant applications
|
|
15
|
+
* - Context selector for multi-organisation and multi-event applications
|
|
17
16
|
* - Custom actions support
|
|
18
17
|
* - Responsive design
|
|
19
18
|
* - Accessibility compliant
|
|
@@ -33,7 +32,7 @@
|
|
|
33
32
|
*
|
|
34
33
|
* // Header with navigation and custom actions
|
|
35
34
|
* <Header
|
|
36
|
-
* logo
|
|
35
|
+
* logoUrl="/logo.svg"
|
|
37
36
|
* logoHref="/home"
|
|
38
37
|
* navItems={[
|
|
39
38
|
* { id: 'dashboard', label: 'Dashboard', href: '/dashboard' },
|
|
@@ -83,17 +82,18 @@
|
|
|
83
82
|
* - Tailwind CSS - Styling
|
|
84
83
|
* - NavigationMenu component
|
|
85
84
|
* - UserMenu component
|
|
86
|
-
* - ContextSelector component
|
|
85
|
+
* - ContextSelector component
|
|
87
86
|
*/
|
|
88
87
|
|
|
89
88
|
import React from 'react';
|
|
90
89
|
import { Link } from 'react-router-dom';
|
|
90
|
+
import { AppSwitcher } from '../AppSwitcher/AppSwitcher';
|
|
91
|
+
import { useUnifiedAuth } from '../../providers/services/UnifiedAuthProvider';
|
|
91
92
|
import { User } from '@supabase/supabase-js';
|
|
92
93
|
import { cn } from '../../utils/core/cn';
|
|
93
94
|
import { ContextSelector } from '../ContextSelector';
|
|
94
95
|
import { UserMenu } from '../UserMenu';
|
|
95
|
-
import { NavigationMenu } from '../NavigationMenu';
|
|
96
|
-
import type { NavigationItem } from '../NavigationMenu';
|
|
96
|
+
import { NavigationMenu, type NavigationItem } from '../NavigationMenu';
|
|
97
97
|
import type { PasswordChangeFormError } from '../PasswordChange/PasswordChangeForm';
|
|
98
98
|
import { useOrganisations } from '../../hooks/useOrganisations';
|
|
99
99
|
import { useEvents } from '../../hooks/useEvents';
|
|
@@ -107,8 +107,6 @@ export interface HeaderProps {
|
|
|
107
107
|
logoUrl?: string;
|
|
108
108
|
/** Alt text for the logo */
|
|
109
109
|
logoAlt?: string;
|
|
110
|
-
/** Custom logo component (overrides logoUrl) */
|
|
111
|
-
logo?: React.ReactNode;
|
|
112
110
|
/** Navigation items for the menu - uses NavigationItem interface */
|
|
113
111
|
navItems?: NavigationItem[];
|
|
114
112
|
/** Current user for the user menu */
|
|
@@ -117,13 +115,13 @@ export interface HeaderProps {
|
|
|
117
115
|
onSignOut?: () => Promise<void>;
|
|
118
116
|
/** Password change handler for user menu */
|
|
119
117
|
onChangePassword?: (newPassword: string, confirmPassword: string) => Promise<{ error?: PasswordChangeFormError }>;
|
|
120
|
-
/** Additional actions to display (will be placed between
|
|
118
|
+
/** Additional actions to display (will be placed between context selector and user menu) */
|
|
121
119
|
actions?: React.ReactNode;
|
|
122
120
|
/** Custom user menu component (overrides default UserMenu) */
|
|
123
121
|
userMenu?: React.ReactNode;
|
|
124
122
|
/** Custom className */
|
|
125
123
|
className?: string;
|
|
126
|
-
/** Show/hide context selector
|
|
124
|
+
/** Show/hide context selector - default: true */
|
|
127
125
|
showContextSelector?: boolean;
|
|
128
126
|
/** Show organisations in context selector - default: true */
|
|
129
127
|
showOrganisations?: boolean;
|
|
@@ -135,7 +133,7 @@ export interface HeaderProps {
|
|
|
135
133
|
currentPath?: string;
|
|
136
134
|
/** Custom navigation handler */
|
|
137
135
|
onNavigate?: (item: NavigationItem) => void;
|
|
138
|
-
/** URL to navigate to when logo is clicked (e.g., '/dashboard') */
|
|
136
|
+
/** URL to navigate to when logo is clicked (e.g., '/dashboard'). Defaults to '/' if not provided. */
|
|
139
137
|
logoHref?: string;
|
|
140
138
|
}
|
|
141
139
|
|
|
@@ -152,11 +150,11 @@ export interface HeaderProps {
|
|
|
152
150
|
* authenticated and public pages.
|
|
153
151
|
*
|
|
154
152
|
* Features:
|
|
155
|
-
* - Customizable logo
|
|
153
|
+
* - Customizable logo via URL
|
|
156
154
|
* - Clickable logo that automatically routes to dashboard (configurable via logoHref)
|
|
157
155
|
* - Navigation menu integration with highlighting
|
|
158
156
|
* - User menu with authentication and password management
|
|
159
|
-
* -
|
|
157
|
+
* - Context selector for multi-organisation and multi-event applications
|
|
160
158
|
* - Custom actions support
|
|
161
159
|
* - Responsive design with mobile considerations
|
|
162
160
|
* - Accessibility compliant with proper ARIA attributes
|
|
@@ -242,15 +240,17 @@ export interface HeaderProps {
|
|
|
242
240
|
*/
|
|
243
241
|
/**
|
|
244
242
|
* Header component for application layouts.
|
|
245
|
-
* Provides navigation, user menu,
|
|
243
|
+
* Provides navigation, user menu, context selector, and customizable branding.
|
|
246
244
|
*
|
|
247
245
|
* @param props - Header configuration
|
|
248
246
|
* @returns The rendered header
|
|
249
247
|
*/
|
|
248
|
+
// Default logo SVG data URL (simple white square 32x32)
|
|
249
|
+
const DEFAULT_LOGO_SRC = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmYiLz48L3N2Zz4=';
|
|
250
|
+
|
|
250
251
|
export function Header({
|
|
251
252
|
logoUrl,
|
|
252
253
|
logoAlt = 'Logo',
|
|
253
|
-
logo,
|
|
254
254
|
navItems = [],
|
|
255
255
|
user,
|
|
256
256
|
onSignOut,
|
|
@@ -272,55 +272,68 @@ export function Header({
|
|
|
272
272
|
// Get hooks for context selector
|
|
273
273
|
const { switchOrganisation } = useOrganisations();
|
|
274
274
|
const { events, setSelectedEvent } = useEvents();
|
|
275
|
+
|
|
276
|
+
// Get app name for app switcher (only if user is authenticated)
|
|
277
|
+
const authContext = useUnifiedAuth();
|
|
278
|
+
const isAuthenticated = authContext?.isAuthenticated ?? false;
|
|
279
|
+
const appName = authContext?.appName;
|
|
275
280
|
|
|
276
281
|
return (
|
|
277
282
|
<header className={cn(
|
|
278
283
|
"w-full border-b border-main-200 h-16 shadow-sm bg-main-100 ",
|
|
279
284
|
className
|
|
280
285
|
)} role="banner">
|
|
281
|
-
<nav className=
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
286
|
+
<nav className={cn(
|
|
287
|
+
"px-4 w-[min(var(--app-width),100%)] mx-auto grid items-center gap-4 h-full",
|
|
288
|
+
isAuthenticated && appName
|
|
289
|
+
? "grid-cols-[auto_auto_1fr_auto_auto]"
|
|
290
|
+
: "grid-cols-[auto_1fr_auto_auto]"
|
|
291
|
+
)}>
|
|
292
|
+
{/* PACE Logo with App Switcher (if authenticated) */}
|
|
293
|
+
{isAuthenticated && appName && (
|
|
294
|
+
<AppSwitcher
|
|
295
|
+
currentAppName={appName}
|
|
296
|
+
className="w-9"
|
|
297
|
+
/>
|
|
298
|
+
)}
|
|
299
|
+
|
|
300
|
+
{/* App Logo (regular link, not app switcher) */}
|
|
301
|
+
{logoUrl && (
|
|
292
302
|
logoHref ? (
|
|
293
|
-
<Link to={logoHref} className="cursor-pointer hover:opacity-80 transition-opacity">
|
|
303
|
+
<Link to={logoHref} className="cursor-pointer hover:opacity-80 transition-opacity flex items-center">
|
|
294
304
|
<img
|
|
295
305
|
src={logoUrl}
|
|
296
306
|
alt={logoAlt || 'Logo'}
|
|
297
|
-
className="h-
|
|
307
|
+
className="h-9 w-auto shadow-md"
|
|
298
308
|
/>
|
|
299
309
|
</Link>
|
|
300
310
|
) : (
|
|
301
311
|
<img
|
|
302
312
|
src={logoUrl}
|
|
303
313
|
alt={logoAlt || 'Logo'}
|
|
304
|
-
className="h-
|
|
314
|
+
className="h-9 w-auto shadow-md"
|
|
305
315
|
/>
|
|
306
316
|
)
|
|
307
|
-
)
|
|
317
|
+
)}
|
|
318
|
+
{!logoUrl && (
|
|
319
|
+
// Default logo when logoUrl is not provided
|
|
308
320
|
logoHref ? (
|
|
309
|
-
<Link to={logoHref} className="cursor-pointer hover:opacity-80 transition-opacity">
|
|
321
|
+
<Link to={logoHref} className="cursor-pointer hover:opacity-80 transition-opacity flex items-center">
|
|
310
322
|
<img
|
|
311
|
-
src=
|
|
323
|
+
src={DEFAULT_LOGO_SRC}
|
|
312
324
|
alt={logoAlt || 'Logo'}
|
|
313
|
-
className="
|
|
325
|
+
className="h-9 w-auto shadow-md"
|
|
314
326
|
/>
|
|
315
327
|
</Link>
|
|
316
328
|
) : (
|
|
317
329
|
<img
|
|
318
|
-
src=
|
|
330
|
+
src={DEFAULT_LOGO_SRC}
|
|
319
331
|
alt={logoAlt || 'Logo'}
|
|
320
|
-
className="
|
|
332
|
+
className="h-9 w-auto shadow-md"
|
|
321
333
|
/>
|
|
322
334
|
)
|
|
323
335
|
)}
|
|
336
|
+
|
|
324
337
|
|
|
325
338
|
{/* Navigation Menu */}
|
|
326
339
|
{navItems && navItems.length > 0 && (
|
|
@@ -334,15 +347,11 @@ export function Header({
|
|
|
334
347
|
/>
|
|
335
348
|
)}
|
|
336
349
|
|
|
337
|
-
{/*
|
|
350
|
+
{/* Context Selector - Shows all accessible orgs and events */}
|
|
338
351
|
{shouldShowContextSelector ? (
|
|
339
352
|
<ContextSelector
|
|
340
353
|
placeholder="Select organisation or event"
|
|
341
|
-
className=
|
|
342
|
-
"w-96",
|
|
343
|
-
// Adjust width based on whether actions exist
|
|
344
|
-
actions ? "col-span-1" : "col-span-2"
|
|
345
|
-
)}
|
|
354
|
+
className="w-96"
|
|
346
355
|
showOrganisations={showOrganisations}
|
|
347
356
|
showEvents={showEvents}
|
|
348
357
|
onOrganisationSelect={async (org) => {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import React from 'react';
|
|
8
|
-
import { screen
|
|
8
|
+
import { screen } from '@testing-library/react';
|
|
9
9
|
import userEvent from '@testing-library/user-event';
|
|
10
10
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
11
11
|
import { InactivityWarningModal } from './InactivityWarningModal';
|
|
@@ -13,7 +13,7 @@ import { renderWithProviders } from '../../__tests__/helpers/test-utils';
|
|
|
13
13
|
|
|
14
14
|
// Mock the Dialog components to avoid complex modal behavior in tests
|
|
15
15
|
vi.mock('../Dialog/Dialog', () => ({
|
|
16
|
-
Dialog: ({ children, open,
|
|
16
|
+
Dialog: ({ children, open, _onOpenChange }: { children: React.ReactNode; open: boolean; _onOpenChange: (open: boolean) => void }) =>
|
|
17
17
|
open ? <div data-testid="dialog" role="dialog">{children}</div> : null,
|
|
18
18
|
DialogContent: ({ children, className, preventCloseOnEscape, preventCloseOnOutsideClick, ...props }: any) => (
|
|
19
19
|
<div
|
|
@@ -110,34 +110,16 @@ describe('InactivityWarningModal Component', () => {
|
|
|
110
110
|
expect(modal).toHaveClass('custom-modal');
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
it(
|
|
114
|
-
|
|
113
|
+
it.each([
|
|
114
|
+
{ timeRemaining: 0, expected: '00:00' },
|
|
115
|
+
{ timeRemaining: 5, expected: '00:05' },
|
|
116
|
+
{ timeRemaining: 60, expected: '01:00' },
|
|
117
|
+
{ timeRemaining: 65, expected: '01:05' },
|
|
118
|
+
{ timeRemaining: 125, expected: '02:05' },
|
|
119
|
+
])('renders countdown timer with correct format (timeRemaining: $timeRemaining)', ({ timeRemaining, expected }) => {
|
|
120
|
+
renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={timeRemaining} />);
|
|
115
121
|
|
|
116
|
-
expect(screen.getByText(
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('renders countdown timer with single digit minutes', () => {
|
|
120
|
-
renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={65} />);
|
|
121
|
-
|
|
122
|
-
expect(screen.getByText('01:05')).toBeInTheDocument();
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('renders countdown timer with zero seconds', () => {
|
|
126
|
-
renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={60} />);
|
|
127
|
-
|
|
128
|
-
expect(screen.getByText('01:00')).toBeInTheDocument();
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('renders countdown timer with single digit seconds', () => {
|
|
132
|
-
renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={5} />);
|
|
133
|
-
|
|
134
|
-
expect(screen.getByText('00:05')).toBeInTheDocument();
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('renders countdown timer with zero time', () => {
|
|
138
|
-
renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={0} />);
|
|
139
|
-
|
|
140
|
-
expect(screen.getByText('00:00')).toBeInTheDocument();
|
|
122
|
+
expect(screen.getByText(expected)).toBeInTheDocument();
|
|
141
123
|
});
|
|
142
124
|
|
|
143
125
|
it('renders action buttons with correct text', () => {
|
|
@@ -162,25 +144,20 @@ describe('InactivityWarningModal Component', () => {
|
|
|
162
144
|
});
|
|
163
145
|
|
|
164
146
|
describe('Time Formatting', () => {
|
|
165
|
-
it(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
expect(screen.getByText(expected)).toBeInTheDocument();
|
|
182
|
-
unmount();
|
|
183
|
-
});
|
|
147
|
+
it.each([
|
|
148
|
+
{ input: 0, expected: '00:00' },
|
|
149
|
+
{ input: 5, expected: '00:05' },
|
|
150
|
+
{ input: 30, expected: '00:30' },
|
|
151
|
+
{ input: 60, expected: '01:00' },
|
|
152
|
+
{ input: 90, expected: '01:30' },
|
|
153
|
+
{ input: 125, expected: '02:05' },
|
|
154
|
+
{ input: 3661, expected: '61:01' },
|
|
155
|
+
])('formats time correctly (input: $input, expected: $expected)', ({ input, expected }) => {
|
|
156
|
+
renderWithProviders(
|
|
157
|
+
<InactivityWarningModal {...baseProps} timeRemaining={input} />
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
expect(screen.getByText(expected)).toBeInTheDocument();
|
|
184
161
|
});
|
|
185
162
|
|
|
186
163
|
it('updates display time when timeRemaining prop changes', () => {
|
|
@@ -318,20 +295,16 @@ describe('InactivityWarningModal Component', () => {
|
|
|
318
295
|
});
|
|
319
296
|
|
|
320
297
|
describe('Edge Cases', () => {
|
|
321
|
-
it(
|
|
322
|
-
|
|
298
|
+
it.each([
|
|
299
|
+
{ timeRemaining: -5, expected: '-1:-5', description: 'negative time' },
|
|
300
|
+
{ timeRemaining: 999999, expected: '16666:39', description: 'very large time' },
|
|
301
|
+
])('handles $description gracefully', ({ timeRemaining, expected }) => {
|
|
302
|
+
renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={timeRemaining} />);
|
|
323
303
|
|
|
324
|
-
|
|
325
|
-
expect(screen.getByText('-1:-5')).toBeInTheDocument();
|
|
304
|
+
expect(screen.getByText(expected)).toBeInTheDocument();
|
|
326
305
|
});
|
|
327
306
|
|
|
328
|
-
it('
|
|
329
|
-
renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={999999} />);
|
|
330
|
-
|
|
331
|
-
expect(screen.getByText('16666:39')).toBeInTheDocument();
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
it('handles undefined title and description', () => {
|
|
307
|
+
it('uses default title and description when undefined', () => {
|
|
335
308
|
const propsWithoutDefaults = {
|
|
336
309
|
isOpen: true,
|
|
337
310
|
timeRemaining: 30,
|
|
@@ -343,12 +316,11 @@ describe('InactivityWarningModal Component', () => {
|
|
|
343
316
|
|
|
344
317
|
renderWithProviders(<InactivityWarningModal {...propsWithoutDefaults} />);
|
|
345
318
|
|
|
346
|
-
// Should use default values
|
|
347
319
|
expect(screen.getByText('Session Timeout Warning')).toBeInTheDocument();
|
|
348
320
|
expect(screen.getByText("You've been inactive for a while. Your session will expire soon for security reasons.")).toBeInTheDocument();
|
|
349
321
|
});
|
|
350
322
|
|
|
351
|
-
it('
|
|
323
|
+
it('renders empty strings when title and description are empty', () => {
|
|
352
324
|
renderWithProviders(
|
|
353
325
|
<InactivityWarningModal
|
|
354
326
|
{...baseProps}
|
|
@@ -357,13 +329,8 @@ describe('InactivityWarningModal Component', () => {
|
|
|
357
329
|
/>
|
|
358
330
|
);
|
|
359
331
|
|
|
360
|
-
// Should render empty strings - title is h2, description is p in DialogHeader
|
|
361
332
|
const title = screen.getByRole('heading', { level: 2 });
|
|
362
|
-
const description = screen.getByText(/Time remaining/i).closest('div')?.previousElementSibling?.querySelector('p');
|
|
363
333
|
expect(title).toHaveTextContent('');
|
|
364
|
-
if (description) {
|
|
365
|
-
expect(description).toHaveTextContent('');
|
|
366
|
-
}
|
|
367
334
|
});
|
|
368
335
|
});
|
|
369
336
|
|
|
@@ -439,21 +406,14 @@ describe('InactivityWarningModal Component', () => {
|
|
|
439
406
|
|
|
440
407
|
renderWithProviders(<InactivityWarningModal {...propsWithoutCallbacks} />);
|
|
441
408
|
|
|
442
|
-
// Should render without errors
|
|
443
409
|
expect(screen.getByTestId('dialog')).toBeInTheDocument();
|
|
444
410
|
expect(screen.getByRole('button', { name: 'Stay Signed In' })).toBeInTheDocument();
|
|
445
411
|
expect(screen.getByRole('button', { name: 'Sign Out Now' })).toBeInTheDocument();
|
|
446
412
|
});
|
|
447
413
|
|
|
448
|
-
it('handles invalid timeRemaining values', () => {
|
|
449
|
-
|
|
450
|
-
...baseProps,
|
|
451
|
-
timeRemaining: NaN,
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
renderWithProviders(<InactivityWarningModal {...invalidTimeProps} />);
|
|
414
|
+
it('handles invalid timeRemaining values (NaN)', () => {
|
|
415
|
+
renderWithProviders(<InactivityWarningModal {...baseProps} timeRemaining={NaN} />);
|
|
455
416
|
|
|
456
|
-
// Should render with NaN formatted as "NaN:NaN" or handle gracefully
|
|
457
417
|
expect(screen.getByTestId('dialog')).toBeInTheDocument();
|
|
458
418
|
});
|
|
459
419
|
});
|
|
@@ -473,7 +433,6 @@ describe('InactivityWarningModal Component', () => {
|
|
|
473
433
|
<InactivityWarningModal {...stableProps} />
|
|
474
434
|
);
|
|
475
435
|
|
|
476
|
-
const initialTime = screen.getByText('00:30');
|
|
477
436
|
|
|
478
437
|
// Re-render with same props
|
|
479
438
|
rerender(<InactivityWarningModal {...stableProps} />);
|
|
@@ -59,47 +59,25 @@ describe('Input Component', () => {
|
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
describe('Variants', () => {
|
|
62
|
-
it(
|
|
63
|
-
|
|
62
|
+
it.each([
|
|
63
|
+
{ variant: 'default' as const, description: 'default variant' },
|
|
64
|
+
{ variant: 'destructive' as const, description: 'destructive variant' },
|
|
65
|
+
{ error: true, description: 'error prop' },
|
|
66
|
+
])('renders with $description', (props) => {
|
|
67
|
+
renderWithProviders(<Input {...props} />);
|
|
64
68
|
const input = screen.getByRole('textbox');
|
|
65
69
|
expect(input).toBeInTheDocument();
|
|
66
70
|
expect(input).toBeVisible();
|
|
67
71
|
});
|
|
68
|
-
|
|
69
|
-
it('renders with destructive variant', () => {
|
|
70
|
-
renderWithProviders(<Input variant="destructive" />);
|
|
71
|
-
const input = screen.getByRole('textbox');
|
|
72
|
-
// Verify destructive variant is rendered (behavior-based check)
|
|
73
|
-
expect(input).toBeInTheDocument();
|
|
74
|
-
expect(input).toBeVisible();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('applies destructive styling when error is true', () => {
|
|
78
|
-
renderWithProviders(<Input error={true} />);
|
|
79
|
-
const input = screen.getByRole('textbox');
|
|
80
|
-
// Verify error state is applied (behavior-based check)
|
|
81
|
-
expect(input).toBeInTheDocument();
|
|
82
|
-
expect(input).toBeVisible();
|
|
83
|
-
});
|
|
84
72
|
});
|
|
85
73
|
|
|
86
74
|
describe('Sizes', () => {
|
|
87
|
-
it(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
it('renders with medium size (default)', () => {
|
|
95
|
-
renderWithProviders(<Input size="md" />);
|
|
96
|
-
const input = screen.getByRole('textbox');
|
|
97
|
-
expect(input).toBeInTheDocument();
|
|
98
|
-
expect(input).toBeVisible();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('renders with large size', () => {
|
|
102
|
-
renderWithProviders(<Input size="lg" />);
|
|
75
|
+
it.each([
|
|
76
|
+
{ size: 'sm' as const },
|
|
77
|
+
{ size: 'md' as const },
|
|
78
|
+
{ size: 'lg' as const },
|
|
79
|
+
])('renders with $size size', ({ size }) => {
|
|
80
|
+
renderWithProviders(<Input size={size} />);
|
|
103
81
|
const input = screen.getByRole('textbox');
|
|
104
82
|
expect(input).toBeInTheDocument();
|
|
105
83
|
expect(input).toBeVisible();
|
|
@@ -228,16 +206,22 @@ describe('Input Component', () => {
|
|
|
228
206
|
it('handles error state styling', () => {
|
|
229
207
|
renderWithProviders(<Input error={true} />);
|
|
230
208
|
const input = screen.getByRole('textbox');
|
|
231
|
-
// Verify error state is applied (behavior-based check)
|
|
232
209
|
expect(input).toBeInTheDocument();
|
|
233
210
|
expect(input).toBeVisible();
|
|
234
211
|
});
|
|
235
212
|
|
|
236
|
-
it('handles invalid input gracefully', () => {
|
|
213
|
+
it('handles invalid input values gracefully', () => {
|
|
237
214
|
renderWithProviders(<Input type="email" value="invalid-email" />);
|
|
238
215
|
const input = screen.getByRole('textbox');
|
|
239
216
|
expect(input).toHaveValue('invalid-email');
|
|
240
217
|
});
|
|
218
|
+
|
|
219
|
+
it('handles readOnly state', () => {
|
|
220
|
+
renderWithProviders(<Input readOnly value="readonly value" />);
|
|
221
|
+
const input = screen.getByRole('textbox');
|
|
222
|
+
expect(input).toHaveAttribute('readonly');
|
|
223
|
+
expect(input).toHaveValue('readonly value');
|
|
224
|
+
});
|
|
241
225
|
});
|
|
242
226
|
|
|
243
227
|
// Integration tests
|
|
@@ -310,108 +294,38 @@ describe('InputGroup Component', () => {
|
|
|
310
294
|
});
|
|
311
295
|
|
|
312
296
|
describe('Orientation', () => {
|
|
313
|
-
it(
|
|
297
|
+
it.each([
|
|
298
|
+
{ orientation: 'vertical' as const },
|
|
299
|
+
{ orientation: 'horizontal' as const },
|
|
300
|
+
])('renders with $orientation orientation', ({ orientation }) => {
|
|
314
301
|
renderWithProviders(
|
|
315
|
-
<InputGroup orientation=
|
|
302
|
+
<InputGroup orientation={orientation}>
|
|
316
303
|
<Input placeholder="Input 1" />
|
|
317
304
|
<Input placeholder="Input 2" />
|
|
318
305
|
</InputGroup>
|
|
319
306
|
);
|
|
320
307
|
|
|
321
|
-
// Verify inputs are rendered (behavior-based check)
|
|
322
|
-
expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
|
|
323
|
-
expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
it('renders with horizontal orientation', () => {
|
|
327
|
-
renderWithProviders(
|
|
328
|
-
<InputGroup orientation="horizontal">
|
|
329
|
-
<Input placeholder="Input 1" />
|
|
330
|
-
<Input placeholder="Input 2" />
|
|
331
|
-
</InputGroup>
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
// Verify inputs are rendered (behavior-based check)
|
|
335
308
|
expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
|
|
336
309
|
expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
|
|
337
310
|
});
|
|
338
311
|
});
|
|
339
312
|
|
|
340
313
|
describe('Spacing', () => {
|
|
341
|
-
it(
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
// Verify inputs are rendered with spacing (behavior-based check)
|
|
350
|
-
expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
|
|
351
|
-
expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
it('applies medium spacing for vertical orientation (default)', () => {
|
|
355
|
-
renderWithProviders(
|
|
356
|
-
<InputGroup orientation="vertical" spacing="md">
|
|
357
|
-
<Input placeholder="Input 1" />
|
|
358
|
-
<Input placeholder="Input 2" />
|
|
359
|
-
</InputGroup>
|
|
360
|
-
);
|
|
361
|
-
|
|
362
|
-
// Verify inputs are rendered with spacing (behavior-based check)
|
|
363
|
-
expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
|
|
364
|
-
expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
it('applies large spacing for vertical orientation', () => {
|
|
368
|
-
renderWithProviders(
|
|
369
|
-
<InputGroup orientation="vertical" spacing="lg">
|
|
370
|
-
<Input placeholder="Input 1" />
|
|
371
|
-
<Input placeholder="Input 2" />
|
|
372
|
-
</InputGroup>
|
|
373
|
-
);
|
|
374
|
-
|
|
375
|
-
// Verify inputs are rendered with spacing (behavior-based check)
|
|
376
|
-
expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
|
|
377
|
-
expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
it('applies small spacing for horizontal orientation', () => {
|
|
381
|
-
renderWithProviders(
|
|
382
|
-
<InputGroup orientation="horizontal" spacing="sm">
|
|
383
|
-
<Input placeholder="Input 1" />
|
|
384
|
-
<Input placeholder="Input 2" />
|
|
385
|
-
</InputGroup>
|
|
386
|
-
);
|
|
387
|
-
|
|
388
|
-
// Verify inputs are rendered with spacing (behavior-based check)
|
|
389
|
-
expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
|
|
390
|
-
expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
it('applies medium spacing for horizontal orientation (default)', () => {
|
|
394
|
-
renderWithProviders(
|
|
395
|
-
<InputGroup orientation="horizontal" spacing="md">
|
|
396
|
-
<Input placeholder="Input 1" />
|
|
397
|
-
<Input placeholder="Input 2" />
|
|
398
|
-
</InputGroup>
|
|
399
|
-
);
|
|
400
|
-
|
|
401
|
-
// Verify inputs are rendered with spacing (behavior-based check)
|
|
402
|
-
expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
|
|
403
|
-
expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
it('applies large spacing for horizontal orientation', () => {
|
|
314
|
+
it.each([
|
|
315
|
+
{ orientation: 'vertical' as const, spacing: 'sm' as const },
|
|
316
|
+
{ orientation: 'vertical' as const, spacing: 'md' as const },
|
|
317
|
+
{ orientation: 'vertical' as const, spacing: 'lg' as const },
|
|
318
|
+
{ orientation: 'horizontal' as const, spacing: 'sm' as const },
|
|
319
|
+
{ orientation: 'horizontal' as const, spacing: 'md' as const },
|
|
320
|
+
{ orientation: 'horizontal' as const, spacing: 'lg' as const },
|
|
321
|
+
])('applies $spacing spacing for $orientation orientation', ({ orientation, spacing }) => {
|
|
407
322
|
renderWithProviders(
|
|
408
|
-
<InputGroup orientation=
|
|
323
|
+
<InputGroup orientation={orientation} spacing={spacing}>
|
|
409
324
|
<Input placeholder="Input 1" />
|
|
410
325
|
<Input placeholder="Input 2" />
|
|
411
326
|
</InputGroup>
|
|
412
327
|
);
|
|
413
328
|
|
|
414
|
-
// Verify inputs are rendered with spacing (behavior-based check)
|
|
415
329
|
expect(screen.getByPlaceholderText('Input 1')).toBeInTheDocument();
|
|
416
330
|
expect(screen.getByPlaceholderText('Input 2')).toBeInTheDocument();
|
|
417
331
|
});
|