@jmruthers/pace-core 0.5.191 → 0.6.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/CHANGELOG.md +29 -0
- package/README.md +7 -1
- package/cursor-rules/00-pace-core-compliance.mdc +372 -0
- package/cursor-rules/01-standards-compliance.mdc +275 -0
- package/cursor-rules/02-project-structure.mdc +200 -0
- package/cursor-rules/03-solid-principles.mdc +341 -0
- package/cursor-rules/04-testing-standards.mdc +315 -0
- package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
- package/cursor-rules/06-code-quality.mdc +392 -0
- package/cursor-rules/07-tech-stack-compliance.mdc +309 -0
- package/cursor-rules/CHANGELOG.md +101 -0
- package/cursor-rules/README.md +191 -0
- package/dist/{AuthService-CbP_utw2.d.ts → AuthService-DjnJHDtC.d.ts} +1 -0
- package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-CH1U5Tpy.d.ts} +1 -1
- package/dist/{DataTable-WKRZD47S.js → DataTable-DQ7RSOHE.js} +8 -7
- package/dist/{PublicPageProvider-ULXC_u6U.d.ts → PublicPageProvider-ce4xlHYA.d.ts} +37 -156
- package/dist/{UnifiedAuthProvider-BYA9qB-o.d.ts → UnifiedAuthProvider-185Ih4dj.d.ts} +2 -0
- package/dist/{UnifiedAuthProvider-FTSG5XH7.js → UnifiedAuthProvider-ATAP5UTR.js} +3 -3
- package/dist/{api-IHKALJZD.js → api-N774RPUA.js} +2 -2
- package/dist/{chunk-6C4YBBJM.js → chunk-3QRJFVBR.js} +1 -1
- package/dist/chunk-3QRJFVBR.js.map +1 -0
- package/dist/{chunk-OETXORNB.js → chunk-3XTALGJF.js} +211 -136
- package/dist/chunk-3XTALGJF.js.map +1 -0
- package/dist/{chunk-6TQDD426.js → chunk-4N5C5XZU.js} +47 -228
- package/dist/chunk-4N5C5XZU.js.map +1 -0
- package/dist/{chunk-LOMZXPSN.js → chunk-4ZC4GX36.js} +47 -74
- package/dist/chunk-4ZC4GX36.js.map +1 -0
- package/dist/{chunk-6LTQQAT6.js → chunk-BYFSK72L.js} +357 -158
- package/dist/chunk-BYFSK72L.js.map +1 -0
- package/dist/{chunk-XYXSXPUK.js → chunk-EXUD6RNJ.js} +50 -10
- package/dist/chunk-EXUD6RNJ.js.map +1 -0
- package/dist/{chunk-VKB2CO4Z.js → chunk-GLK6VM3F.js} +244 -249
- package/dist/chunk-GLK6VM3F.js.map +1 -0
- package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
- package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
- package/dist/{chunk-XNYQOL3Z.js → chunk-JBKQ3SAO.js} +9 -18
- package/dist/chunk-JBKQ3SAO.js.map +1 -0
- package/dist/{chunk-ROXMHMY2.js → chunk-KNC55RTG.js} +13 -3
- package/dist/{chunk-ROXMHMY2.js.map → chunk-KNC55RTG.js.map} +1 -1
- package/dist/{chunk-QWWZ5CAQ.js → chunk-LXQLPRQ2.js} +2 -2
- package/dist/{chunk-ULHIJK66.js → chunk-T33XF5ZC.js} +255 -140
- package/dist/chunk-T33XF5ZC.js.map +1 -0
- package/dist/{chunk-VRGWKHDB.js → chunk-XM25TVIE.js} +100 -33
- package/dist/chunk-XM25TVIE.js.map +1 -0
- package/dist/components.d.ts +4 -4
- package/dist/components.js +9 -9
- package/dist/hooks.d.ts +6 -6
- package/dist/hooks.js +20 -25
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +11 -11
- package/dist/index.js +18 -21
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +3 -3
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +2 -20
- package/dist/rbac/index.js +7 -9
- package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-BJAlWfuJ.d.ts} +3 -3
- package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +3 -3
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +2 -2
- package/docs/api/classes/RBACAuditManager.md +2 -2
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +2 -2
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +10 -10
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +1 -1
- package/docs/api/interfaces/AddressFieldRef.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CalendarProps.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/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +24 -11
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +1 -1
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.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/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +2 -2
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.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 +1 -1
- 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/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
- package/docs/api/interfaces/ProgressProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.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/QuickFix.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +2 -2
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +2 -2
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +2 -2
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +2 -2
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +2 -2
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +2 -2
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +2 -2
- package/docs/api/interfaces/RouteConfig.md +2 -2
- package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- package/docs/api/interfaces/SetupIssue.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/SwitchProps.md +1 -1
- package/docs/api/interfaces/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +1 -1
- package/docs/api/interfaces/TextareaProps.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 +60 -38
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.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 +2 -2
- 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/UsePublicFileDisplayOptions.md +2 -2
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.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 +194 -209
- package/docs/getting-started/cursor-rules.md +262 -0
- package/docs/getting-started/installation-guide.md +6 -1
- package/docs/getting-started/quick-start.md +6 -1
- package/docs/migration/MIGRATION_GUIDE.md +4 -4
- package/docs/migration/REACT_19_MIGRATION.md +227 -0
- package/docs/migration/database-changes-december-2025.md +2 -1
- package/docs/rbac/event-based-apps.md +124 -6
- package/docs/standards/README.md +39 -0
- package/docs/troubleshooting/migration.md +4 -4
- package/examples/PublicPages/PublicEventPage.tsx +1 -1
- package/package.json +11 -6
- package/scripts/audit-consuming-app.cjs +961 -0
- package/scripts/check-pace-core-compliance.cjs +315 -61
- package/scripts/install-cursor-rules.cjs +236 -0
- package/src/__tests__/helpers/test-providers.tsx +1 -1
- package/src/__tests__/helpers/test-utils.tsx +1 -1
- package/src/__tests__/rls-policies.test.ts +3 -1
- package/src/components/Badge/Badge.tsx +2 -4
- package/src/components/Button/Button.tsx +5 -4
- package/src/components/Calendar/Calendar.tsx +1 -1
- package/src/components/DataTable/DataTable.test.tsx +57 -93
- package/src/components/DataTable/DataTable.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +172 -45
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +121 -28
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +9 -8
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +20 -52
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +170 -34
- package/src/components/DataTable/__tests__/keyboard.test.tsx +75 -12
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +88 -16
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
- package/src/components/DataTable/components/AccessDeniedPage.tsx +1 -1
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
- package/src/components/DataTable/components/DataTableCore.tsx +4 -7
- package/src/components/DataTable/components/DataTableModals.tsx +1 -1
- package/src/components/DataTable/components/EditableRow.tsx +1 -1
- package/src/components/DataTable/components/UnifiedTableBody.tsx +86 -17
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
- package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
- package/src/components/DataTable/hooks/useColumnReordering.ts +2 -2
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +75 -10
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
- package/src/components/Dialog/Dialog.tsx +6 -5
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +1 -1
- package/src/components/EventSelector/EventSelector.tsx +1 -1
- package/src/components/FileDisplay/FileDisplay.test.tsx +4 -3
- package/src/components/FileDisplay/FileDisplay.tsx +16 -4
- package/src/components/Footer/Footer.tsx +1 -1
- package/src/components/Form/Form.test.tsx +36 -15
- package/src/components/Form/Form.tsx +30 -26
- package/src/components/Header/Header.tsx +1 -1
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
- package/src/components/Input/Input.tsx +28 -30
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
- package/src/components/LoginForm/LoginForm.test.tsx +42 -42
- package/src/components/LoginForm/LoginForm.tsx +8 -8
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +6 -4
- package/src/components/NavigationMenu/NavigationMenu.tsx +2 -11
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +0 -1
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +75 -52
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +98 -69
- package/src/components/PaceAppLayout/README.md +1 -1
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +1 -8
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
- package/src/components/PasswordChange/PasswordChangeForm.tsx +1 -1
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +5 -9
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +0 -1
- package/src/components/PublicLayout/PublicPageLayout.tsx +1 -1
- package/src/components/PublicLayout/PublicPageProvider.tsx +0 -1
- package/src/components/Select/Select.tsx +33 -22
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +1 -1
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Textarea/Textarea.tsx +27 -29
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.tsx +1 -1
- package/src/components/UserMenu/UserMenu.tsx +1 -1
- package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +14 -7
- package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
- package/src/hooks/public/usePublicEvent.ts +1 -1
- package/src/hooks/public/usePublicEventLogo.ts +1 -1
- package/src/hooks/public/usePublicRouteParams.ts +1 -1
- package/src/hooks/services/useAuthService.ts +21 -3
- package/src/hooks/services/useEventService.ts +21 -3
- package/src/hooks/services/useInactivityService.ts +21 -3
- package/src/hooks/services/useOrganisationService.ts +21 -3
- package/src/hooks/useDataTableState.ts +8 -18
- package/src/hooks/useFileDisplay.ts +10 -17
- package/src/hooks/useFocusManagement.ts +2 -2
- package/src/hooks/useFocusTrap.ts +4 -4
- package/src/hooks/useFormDialog.ts +8 -7
- package/src/hooks/useInactivityTracker.ts +1 -1
- package/src/hooks/usePermissionCache.ts +1 -1
- package/src/hooks/useSecureDataAccess.test.ts +16 -9
- package/src/hooks/useSecureDataAccess.ts +22 -6
- package/src/hooks/useToast.ts +2 -2
- package/src/providers/__tests__/OrganisationProvider.test.tsx +57 -13
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
- package/src/providers/services/EventServiceProvider.tsx +0 -8
- package/src/providers/services/UnifiedAuthProvider.tsx +196 -46
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +13 -3
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +34 -40
- package/src/rbac/__tests__/isSuperAdmin.real.test.ts +82 -0
- package/src/rbac/adapters.tsx +3 -22
- package/src/rbac/api.test.ts +2 -2
- package/src/rbac/api.ts +7 -1
- package/src/rbac/components/EnhancedNavigationMenu.tsx +3 -16
- package/src/rbac/components/NavigationGuard.tsx +2 -11
- package/src/rbac/components/NavigationProvider.tsx +1 -2
- package/src/rbac/components/PagePermissionGuard.tsx +1 -1
- package/src/rbac/components/PagePermissionProvider.tsx +1 -1
- package/src/rbac/components/PermissionEnforcer.tsx +46 -13
- package/src/rbac/components/RoleBasedRouter.tsx +1 -1
- package/src/rbac/components/SecureDataProvider.tsx +1 -2
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +7 -43
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +4 -11
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +3 -3
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +1 -1
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +1 -1
- package/src/rbac/engine.ts +14 -2
- package/src/rbac/hooks/index.ts +0 -3
- package/src/rbac/hooks/usePermissions.ts +51 -11
- package/src/rbac/hooks/useRBAC.ts +3 -13
- package/src/rbac/hooks/useResolvedScope.test.ts +75 -54
- package/src/rbac/hooks/useResolvedScope.ts +58 -33
- package/src/rbac/hooks/useSecureSupabase.ts +4 -9
- package/src/rbac/secureClient.ts +43 -0
- package/src/services/EventService.ts +4 -57
- package/src/services/InactivityService.ts +127 -34
- package/src/services/OrganisationService.ts +68 -10
- package/src/utils/security/secureDataAccess.test.ts +31 -20
- package/src/utils/security/secureDataAccess.ts +4 -3
- package/dist/chunk-6C4YBBJM.js.map +0 -1
- package/dist/chunk-6LTQQAT6.js.map +0 -1
- package/dist/chunk-6TQDD426.js.map +0 -1
- package/dist/chunk-LOMZXPSN.js.map +0 -1
- package/dist/chunk-OETXORNB.js.map +0 -1
- package/dist/chunk-ULHIJK66.js.map +0 -1
- package/dist/chunk-VKB2CO4Z.js.map +0 -1
- package/dist/chunk-VRGWKHDB.js.map +0 -1
- package/dist/chunk-XNYQOL3Z.js.map +0 -1
- package/dist/chunk-XYXSXPUK.js.map +0 -1
- package/scripts/check-pace-core-compliance.js +0 -512
- package/src/rbac/hooks/useSuperAdminBypass.ts +0 -126
- package/src/utils/context/superAdminOverride.ts +0 -58
- /package/dist/{DataTable-WKRZD47S.js.map → DataTable-DQ7RSOHE.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-FTSG5XH7.js.map → UnifiedAuthProvider-ATAP5UTR.js.map} +0 -0
- /package/dist/{api-IHKALJZD.js.map → api-N774RPUA.js.map} +0 -0
- /package/dist/{chunk-QWWZ5CAQ.js.map → chunk-LXQLPRQ2.js.map} +0 -0
- /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
- /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
- /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
- /package/examples/{rbac → RBAC}/index.ts +0 -0
|
@@ -62,7 +62,7 @@ interface TestData extends Record<string, unknown> {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
describe('[component] DataTableModals', () => {
|
|
65
|
-
const
|
|
65
|
+
const baseProps = {
|
|
66
66
|
showImportModal: false,
|
|
67
67
|
onCloseImportModal: vi.fn(),
|
|
68
68
|
onImport: vi.fn(),
|
|
@@ -78,14 +78,14 @@ describe('[component] DataTableModals', () => {
|
|
|
78
78
|
|
|
79
79
|
describe('Rendering', () => {
|
|
80
80
|
it('renders nothing when no modals are open', () => {
|
|
81
|
-
const { container } = render(<DataTableModals {...
|
|
81
|
+
const { container } = render(<DataTableModals {...baseProps} />);
|
|
82
82
|
expect(container.firstChild).toBeNull();
|
|
83
83
|
});
|
|
84
84
|
|
|
85
85
|
it('renders ImportModal when showImportModal is true', () => {
|
|
86
86
|
render(
|
|
87
87
|
<DataTableModals
|
|
88
|
-
{...
|
|
88
|
+
{...baseProps}
|
|
89
89
|
showImportModal={true}
|
|
90
90
|
/>
|
|
91
91
|
);
|
|
@@ -94,7 +94,7 @@ describe('[component] DataTableModals', () => {
|
|
|
94
94
|
});
|
|
95
95
|
|
|
96
96
|
it('does not render ImportModal when showImportModal is false', () => {
|
|
97
|
-
render(<DataTableModals {...
|
|
97
|
+
render(<DataTableModals {...baseProps} />);
|
|
98
98
|
|
|
99
99
|
expect(screen.queryByTestId('import-modal')).not.toBeInTheDocument();
|
|
100
100
|
});
|
|
@@ -104,7 +104,7 @@ describe('[component] DataTableModals', () => {
|
|
|
104
104
|
it('passes isOpen prop to ImportModal', () => {
|
|
105
105
|
render(
|
|
106
106
|
<DataTableModals
|
|
107
|
-
{...
|
|
107
|
+
{...baseProps}
|
|
108
108
|
showImportModal={true}
|
|
109
109
|
/>
|
|
110
110
|
);
|
|
@@ -118,7 +118,7 @@ describe('[component] DataTableModals', () => {
|
|
|
118
118
|
|
|
119
119
|
render(
|
|
120
120
|
<DataTableModals
|
|
121
|
-
{...
|
|
121
|
+
{...baseProps}
|
|
122
122
|
showImportModal={true}
|
|
123
123
|
onCloseImportModal={onCloseImportModal}
|
|
124
124
|
/>
|
|
@@ -138,7 +138,7 @@ describe('[component] DataTableModals', () => {
|
|
|
138
138
|
|
|
139
139
|
render(
|
|
140
140
|
<DataTableModals
|
|
141
|
-
{...
|
|
141
|
+
{...baseProps}
|
|
142
142
|
showImportModal={true}
|
|
143
143
|
importModalConfig={config}
|
|
144
144
|
/>
|
|
@@ -159,7 +159,7 @@ describe('[component] DataTableModals', () => {
|
|
|
159
159
|
|
|
160
160
|
render(
|
|
161
161
|
<DataTableModals
|
|
162
|
-
{...
|
|
162
|
+
{...baseProps}
|
|
163
163
|
showImportModal={true}
|
|
164
164
|
onImport={onImport}
|
|
165
165
|
columns={columns}
|
|
@@ -188,7 +188,7 @@ describe('[component] DataTableModals', () => {
|
|
|
188
188
|
|
|
189
189
|
render(
|
|
190
190
|
<DataTableModals
|
|
191
|
-
{...
|
|
191
|
+
{...baseProps}
|
|
192
192
|
showImportModal={true}
|
|
193
193
|
onImport={onImport}
|
|
194
194
|
columns={columns}
|
|
@@ -209,7 +209,7 @@ describe('[component] DataTableModals', () => {
|
|
|
209
209
|
|
|
210
210
|
render(
|
|
211
211
|
<DataTableModals
|
|
212
|
-
{...
|
|
212
|
+
{...baseProps}
|
|
213
213
|
showImportModal={true}
|
|
214
214
|
onImport={onImport}
|
|
215
215
|
/>
|
|
@@ -230,7 +230,7 @@ describe('[component] DataTableModals', () => {
|
|
|
230
230
|
|
|
231
231
|
const { rerender } = render(
|
|
232
232
|
<DataTableModals
|
|
233
|
-
{...
|
|
233
|
+
{...baseProps}
|
|
234
234
|
showImportModal={false}
|
|
235
235
|
onStoreFocus={onStoreFocus}
|
|
236
236
|
/>
|
|
@@ -238,7 +238,7 @@ describe('[component] DataTableModals', () => {
|
|
|
238
238
|
|
|
239
239
|
rerender(
|
|
240
240
|
<DataTableModals
|
|
241
|
-
{...
|
|
241
|
+
{...baseProps}
|
|
242
242
|
showImportModal={true}
|
|
243
243
|
onStoreFocus={onStoreFocus}
|
|
244
244
|
/>
|
|
@@ -252,7 +252,7 @@ describe('[component] DataTableModals', () => {
|
|
|
252
252
|
|
|
253
253
|
const { rerender } = render(
|
|
254
254
|
<DataTableModals
|
|
255
|
-
{...
|
|
255
|
+
{...baseProps}
|
|
256
256
|
showImportModal={true}
|
|
257
257
|
onRestoreFocus={onRestoreFocus}
|
|
258
258
|
/>
|
|
@@ -260,7 +260,7 @@ describe('[component] DataTableModals', () => {
|
|
|
260
260
|
|
|
261
261
|
rerender(
|
|
262
262
|
<DataTableModals
|
|
263
|
-
{...
|
|
263
|
+
{...baseProps}
|
|
264
264
|
showImportModal={false}
|
|
265
265
|
onRestoreFocus={onRestoreFocus}
|
|
266
266
|
/>
|
|
@@ -274,7 +274,7 @@ describe('[component] DataTableModals', () => {
|
|
|
274
274
|
it('does not call focus handlers when not provided', () => {
|
|
275
275
|
const { rerender } = render(
|
|
276
276
|
<DataTableModals
|
|
277
|
-
{...
|
|
277
|
+
{...baseProps}
|
|
278
278
|
showImportModal={false}
|
|
279
279
|
/>
|
|
280
280
|
);
|
|
@@ -282,7 +282,7 @@ describe('[component] DataTableModals', () => {
|
|
|
282
282
|
expect(() => {
|
|
283
283
|
rerender(
|
|
284
284
|
<DataTableModals
|
|
285
|
-
{...
|
|
285
|
+
{...baseProps}
|
|
286
286
|
showImportModal={true}
|
|
287
287
|
/>
|
|
288
288
|
);
|
|
@@ -300,7 +300,7 @@ describe('[component] DataTableModals', () => {
|
|
|
300
300
|
|
|
301
301
|
render(
|
|
302
302
|
<DataTableModals
|
|
303
|
-
{...
|
|
303
|
+
{...baseProps}
|
|
304
304
|
showImportModal={true}
|
|
305
305
|
onImport={onImport}
|
|
306
306
|
/>
|
|
@@ -330,7 +330,7 @@ describe('[component] DataTableModals', () => {
|
|
|
330
330
|
|
|
331
331
|
render(
|
|
332
332
|
<DataTableModals
|
|
333
|
-
{...
|
|
333
|
+
{...baseProps}
|
|
334
334
|
showImportModal={true}
|
|
335
335
|
onImport={onImport}
|
|
336
336
|
/>
|
|
@@ -361,7 +361,7 @@ describe('[component] DataTableModals', () => {
|
|
|
361
361
|
|
|
362
362
|
render(
|
|
363
363
|
<DataTableModals
|
|
364
|
-
{...
|
|
364
|
+
{...baseProps}
|
|
365
365
|
showImportModal={true}
|
|
366
366
|
onImport={onImport}
|
|
367
367
|
columns={[]}
|
|
@@ -386,7 +386,7 @@ describe('[component] DataTableModals', () => {
|
|
|
386
386
|
|
|
387
387
|
render(
|
|
388
388
|
<DataTableModals
|
|
389
|
-
{...
|
|
389
|
+
{...baseProps}
|
|
390
390
|
showImportModal={true}
|
|
391
391
|
onImport={onImport}
|
|
392
392
|
columns={columns}
|
|
@@ -406,7 +406,7 @@ describe('[component] DataTableModals', () => {
|
|
|
406
406
|
|
|
407
407
|
render(
|
|
408
408
|
<DataTableModals
|
|
409
|
-
{...
|
|
409
|
+
{...baseProps}
|
|
410
410
|
showImportModal={true}
|
|
411
411
|
onImport={undefined as any}
|
|
412
412
|
/>
|
|
@@ -432,7 +432,7 @@ describe('[component] DataTableModals', () => {
|
|
|
432
432
|
|
|
433
433
|
render(
|
|
434
434
|
<DataTableModals
|
|
435
|
-
{...
|
|
435
|
+
{...baseProps}
|
|
436
436
|
showImportModal={true}
|
|
437
437
|
onImport={onImport}
|
|
438
438
|
columns={columns}
|
|
@@ -456,7 +456,7 @@ describe('[component] DataTableModals', () => {
|
|
|
456
456
|
|
|
457
457
|
render(
|
|
458
458
|
<DataTableModals
|
|
459
|
-
{...
|
|
459
|
+
{...baseProps}
|
|
460
460
|
showImportModal={true}
|
|
461
461
|
onImport={onImport}
|
|
462
462
|
columns={columns}
|
|
@@ -179,7 +179,7 @@ describe('[component] EditableRow', () => {
|
|
|
179
179
|
actions: [],
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
-
const
|
|
182
|
+
const baseProps = getDefaultProps();
|
|
183
183
|
|
|
184
184
|
beforeEach(() => {
|
|
185
185
|
vi.clearAllMocks();
|
|
@@ -191,7 +191,7 @@ describe('[component] EditableRow', () => {
|
|
|
191
191
|
|
|
192
192
|
describe('Rendering', () => {
|
|
193
193
|
it('renders editable row with table row structure', () => {
|
|
194
|
-
render(<EditableRow {...
|
|
194
|
+
render(<EditableRow {...baseProps} />);
|
|
195
195
|
|
|
196
196
|
const row = screen.getByRole('row');
|
|
197
197
|
expect(row).toBeInTheDocument();
|
|
@@ -234,7 +234,7 @@ describe('[component] EditableRow', () => {
|
|
|
234
234
|
});
|
|
235
235
|
|
|
236
236
|
it('renders save and cancel buttons', () => {
|
|
237
|
-
render(<EditableRow {...
|
|
237
|
+
render(<EditableRow {...baseProps} />);
|
|
238
238
|
|
|
239
239
|
expect(screen.getByRole('button', { name: /save changes/i })).toBeInTheDocument();
|
|
240
240
|
expect(screen.getByRole('button', { name: /cancel editing/i })).toBeInTheDocument();
|
|
@@ -271,7 +271,7 @@ describe('[component] EditableRow', () => {
|
|
|
271
271
|
const user = userEvent.setup();
|
|
272
272
|
const onSave = vi.fn();
|
|
273
273
|
|
|
274
|
-
render(<EditableRow {...
|
|
274
|
+
render(<EditableRow {...baseProps} onSave={onSave} />);
|
|
275
275
|
|
|
276
276
|
const saveButton = screen.getByRole('button', { name: /save changes/i });
|
|
277
277
|
await user.click(saveButton);
|
|
@@ -437,7 +437,7 @@ describe('[component] EditableRow', () => {
|
|
|
437
437
|
|
|
438
438
|
render(
|
|
439
439
|
<EditableRow
|
|
440
|
-
{...
|
|
440
|
+
{...baseProps}
|
|
441
441
|
editingData={editingData}
|
|
442
442
|
/>
|
|
443
443
|
);
|
|
@@ -447,7 +447,7 @@ describe('[component] EditableRow', () => {
|
|
|
447
447
|
});
|
|
448
448
|
|
|
449
449
|
it('falls back to original row values when editingData is empty', () => {
|
|
450
|
-
render(<EditableRow {...
|
|
450
|
+
render(<EditableRow {...baseProps} editingData={{}} />);
|
|
451
451
|
|
|
452
452
|
expect(screen.getByDisplayValue('John Doe')).toBeInTheDocument();
|
|
453
453
|
expect(screen.getByDisplayValue('john@example.com')).toBeInTheDocument();
|
|
@@ -468,21 +468,21 @@ describe('[component] EditableRow', () => {
|
|
|
468
468
|
|
|
469
469
|
describe('Accessibility', () => {
|
|
470
470
|
it('provides proper ARIA attributes for row', () => {
|
|
471
|
-
render(<EditableRow {...
|
|
471
|
+
render(<EditableRow {...baseProps} />);
|
|
472
472
|
|
|
473
473
|
const row = screen.getByRole('row');
|
|
474
474
|
expect(row).toHaveAttribute('role', 'row');
|
|
475
475
|
});
|
|
476
476
|
|
|
477
477
|
it('provides aria-label for save button', () => {
|
|
478
|
-
render(<EditableRow {...
|
|
478
|
+
render(<EditableRow {...baseProps} />);
|
|
479
479
|
|
|
480
480
|
const saveButton = screen.getByRole('button', { name: /save changes/i });
|
|
481
481
|
expect(saveButton).toHaveAttribute('aria-label', 'Save changes');
|
|
482
482
|
});
|
|
483
483
|
|
|
484
484
|
it('provides aria-label for cancel button', () => {
|
|
485
|
-
render(<EditableRow {...
|
|
485
|
+
render(<EditableRow {...baseProps} />);
|
|
486
486
|
|
|
487
487
|
const cancelButton = screen.getByRole('button', { name: /cancel editing/i });
|
|
488
488
|
expect(cancelButton).toHaveAttribute('aria-label', 'Cancel editing');
|
|
@@ -491,7 +491,7 @@ describe('[component] EditableRow', () => {
|
|
|
491
491
|
|
|
492
492
|
describe('Edge Cases', () => {
|
|
493
493
|
it('handles empty editingData gracefully', () => {
|
|
494
|
-
render(<EditableRow {...
|
|
494
|
+
render(<EditableRow {...baseProps} editingData={{}} />);
|
|
495
495
|
|
|
496
496
|
expect(screen.getByRole('row')).toBeInTheDocument();
|
|
497
497
|
});
|
|
@@ -512,7 +512,7 @@ describe('[component] EditableRow', () => {
|
|
|
512
512
|
const row = createMockRow();
|
|
513
513
|
|
|
514
514
|
expect(() => {
|
|
515
|
-
render(<EditableRow {...
|
|
515
|
+
render(<EditableRow {...baseProps} row={row} />);
|
|
516
516
|
}).not.toThrow();
|
|
517
517
|
});
|
|
518
518
|
});
|
|
@@ -25,7 +25,7 @@ vi.mock('lucide-react', () => ({
|
|
|
25
25
|
}));
|
|
26
26
|
|
|
27
27
|
describe('[component] ExpandButton', () => {
|
|
28
|
-
const
|
|
28
|
+
const baseProps = {
|
|
29
29
|
rowId: 'row-1',
|
|
30
30
|
isExpanded: false,
|
|
31
31
|
hasChildren: true,
|
|
@@ -44,7 +44,7 @@ describe('[component] ExpandButton', () => {
|
|
|
44
44
|
it('returns null when hasChildren is false', () => {
|
|
45
45
|
const { container } = render(
|
|
46
46
|
<ExpandButton
|
|
47
|
-
{...
|
|
47
|
+
{...baseProps}
|
|
48
48
|
hasChildren={false}
|
|
49
49
|
/>
|
|
50
50
|
);
|
|
@@ -53,27 +53,27 @@ describe('[component] ExpandButton', () => {
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
it('renders button when hasChildren is true', () => {
|
|
56
|
-
render(<ExpandButton {...
|
|
56
|
+
render(<ExpandButton {...baseProps} />);
|
|
57
57
|
|
|
58
58
|
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
it('renders ChevronRight icon when not expanded', () => {
|
|
62
|
-
render(<ExpandButton {...
|
|
62
|
+
render(<ExpandButton {...baseProps} isExpanded={false} />);
|
|
63
63
|
|
|
64
64
|
expect(screen.getByTestId('chevron-right-icon')).toBeInTheDocument();
|
|
65
65
|
expect(screen.queryByTestId('chevron-down-icon')).not.toBeInTheDocument();
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
it('renders ChevronDown icon when expanded', () => {
|
|
69
|
-
render(<ExpandButton {...
|
|
69
|
+
render(<ExpandButton {...baseProps} isExpanded={true} />);
|
|
70
70
|
|
|
71
71
|
expect(screen.getByTestId('chevron-down-icon')).toBeInTheDocument();
|
|
72
72
|
expect(screen.queryByTestId('chevron-right-icon')).not.toBeInTheDocument();
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
it('has correct testId attribute', () => {
|
|
76
|
-
render(<ExpandButton {...
|
|
76
|
+
render(<ExpandButton {...baseProps} rowId="test-row-123" />);
|
|
77
77
|
|
|
78
78
|
const button = screen.getByRole('button');
|
|
79
79
|
expect(button).toHaveAttribute('data-testid', 'expand-button-test-row-123');
|
|
@@ -87,7 +87,7 @@ describe('[component] ExpandButton', () => {
|
|
|
87
87
|
|
|
88
88
|
render(
|
|
89
89
|
<ExpandButton
|
|
90
|
-
{...
|
|
90
|
+
{...baseProps}
|
|
91
91
|
onClick={handleClick}
|
|
92
92
|
/>
|
|
93
93
|
);
|
|
@@ -104,7 +104,7 @@ describe('[component] ExpandButton', () => {
|
|
|
104
104
|
|
|
105
105
|
render(
|
|
106
106
|
<ExpandButton
|
|
107
|
-
{...
|
|
107
|
+
{...baseProps}
|
|
108
108
|
onClick={handleClick}
|
|
109
109
|
/>
|
|
110
110
|
);
|
|
@@ -122,7 +122,7 @@ describe('[component] ExpandButton', () => {
|
|
|
122
122
|
|
|
123
123
|
render(
|
|
124
124
|
<ExpandButton
|
|
125
|
-
{...
|
|
125
|
+
{...baseProps}
|
|
126
126
|
onClick={handleClick}
|
|
127
127
|
/>
|
|
128
128
|
);
|
|
@@ -142,7 +142,7 @@ describe('[component] ExpandButton', () => {
|
|
|
142
142
|
render(
|
|
143
143
|
<div onClick={handleParentClick}>
|
|
144
144
|
<ExpandButton
|
|
145
|
-
{...
|
|
145
|
+
{...baseProps}
|
|
146
146
|
onClick={handleClick}
|
|
147
147
|
/>
|
|
148
148
|
</div>
|
|
@@ -163,7 +163,7 @@ describe('[component] ExpandButton', () => {
|
|
|
163
163
|
render(
|
|
164
164
|
<div onKeyDown={handleParentKeyDown}>
|
|
165
165
|
<ExpandButton
|
|
166
|
-
{...
|
|
166
|
+
{...baseProps}
|
|
167
167
|
onClick={handleClick}
|
|
168
168
|
/>
|
|
169
169
|
</div>
|
|
@@ -180,33 +180,33 @@ describe('[component] ExpandButton', () => {
|
|
|
180
180
|
|
|
181
181
|
describe('Accessibility', () => {
|
|
182
182
|
it('has aria-label for collapsed state', () => {
|
|
183
|
-
render(<ExpandButton {...
|
|
183
|
+
render(<ExpandButton {...baseProps} isExpanded={false} />);
|
|
184
184
|
|
|
185
185
|
const button = screen.getByRole('button');
|
|
186
186
|
expect(button).toHaveAttribute('aria-label', 'Expand row');
|
|
187
187
|
});
|
|
188
188
|
|
|
189
189
|
it('has aria-label for expanded state', () => {
|
|
190
|
-
render(<ExpandButton {...
|
|
190
|
+
render(<ExpandButton {...baseProps} isExpanded={true} />);
|
|
191
191
|
|
|
192
192
|
const button = screen.getByRole('button');
|
|
193
193
|
expect(button).toHaveAttribute('aria-label', 'Collapse row');
|
|
194
194
|
});
|
|
195
195
|
|
|
196
196
|
it('has aria-expanded attribute', () => {
|
|
197
|
-
render(<ExpandButton {...
|
|
197
|
+
render(<ExpandButton {...baseProps} isExpanded={false} />);
|
|
198
198
|
|
|
199
199
|
const button = screen.getByRole('button');
|
|
200
200
|
expect(button).toHaveAttribute('aria-expanded', 'false');
|
|
201
201
|
});
|
|
202
202
|
|
|
203
203
|
it('updates aria-expanded when state changes', () => {
|
|
204
|
-
const { rerender } = render(<ExpandButton {...
|
|
204
|
+
const { rerender } = render(<ExpandButton {...baseProps} isExpanded={false} />);
|
|
205
205
|
|
|
206
206
|
let button = screen.getByRole('button');
|
|
207
207
|
expect(button).toHaveAttribute('aria-expanded', 'false');
|
|
208
208
|
|
|
209
|
-
rerender(<ExpandButton {...
|
|
209
|
+
rerender(<ExpandButton {...baseProps} isExpanded={true} />);
|
|
210
210
|
|
|
211
211
|
button = screen.getByRole('button');
|
|
212
212
|
expect(button).toHaveAttribute('aria-expanded', 'true');
|
|
@@ -217,7 +217,7 @@ describe('[component] ExpandButton', () => {
|
|
|
217
217
|
it('applies custom className', () => {
|
|
218
218
|
render(
|
|
219
219
|
<ExpandButton
|
|
220
|
-
{...
|
|
220
|
+
{...baseProps}
|
|
221
221
|
className="custom-class"
|
|
222
222
|
/>
|
|
223
223
|
);
|
|
@@ -227,7 +227,7 @@ describe('[component] ExpandButton', () => {
|
|
|
227
227
|
});
|
|
228
228
|
|
|
229
229
|
it('has proper button styling classes', () => {
|
|
230
|
-
render(<ExpandButton {...
|
|
230
|
+
render(<ExpandButton {...baseProps} />);
|
|
231
231
|
|
|
232
232
|
const button = screen.getByRole('button');
|
|
233
233
|
expect(button.className).toContain('inline-flex');
|
|
@@ -243,7 +243,7 @@ describe('[component] ExpandButton', () => {
|
|
|
243
243
|
|
|
244
244
|
render(
|
|
245
245
|
<ExpandButton
|
|
246
|
-
{...
|
|
246
|
+
{...baseProps}
|
|
247
247
|
onClick={handleClick}
|
|
248
248
|
/>
|
|
249
249
|
);
|
|
@@ -260,7 +260,7 @@ describe('[component] ExpandButton', () => {
|
|
|
260
260
|
expect(() => {
|
|
261
261
|
render(
|
|
262
262
|
<ExpandButton
|
|
263
|
-
{...
|
|
263
|
+
{...baseProps}
|
|
264
264
|
onClick={undefined as any}
|
|
265
265
|
/>
|
|
266
266
|
);
|
|
@@ -270,7 +270,7 @@ describe('[component] ExpandButton', () => {
|
|
|
270
270
|
it('handles empty rowId', () => {
|
|
271
271
|
render(
|
|
272
272
|
<ExpandButton
|
|
273
|
-
{...
|
|
273
|
+
{...baseProps}
|
|
274
274
|
rowId=""
|
|
275
275
|
/>
|
|
276
276
|
);
|
|
@@ -282,7 +282,7 @@ describe('[component] ExpandButton', () => {
|
|
|
282
282
|
});
|
|
283
283
|
|
|
284
284
|
describe('[component] ExpandButtonMinimal', () => {
|
|
285
|
-
const
|
|
285
|
+
const baseProps = {
|
|
286
286
|
rowId: 'row-1',
|
|
287
287
|
isExpanded: false,
|
|
288
288
|
hasChildren: true,
|
|
@@ -301,7 +301,7 @@ describe('[component] ExpandButtonMinimal', () => {
|
|
|
301
301
|
it('returns null when hasChildren is false', () => {
|
|
302
302
|
const { container } = render(
|
|
303
303
|
<ExpandButtonMinimal
|
|
304
|
-
{...
|
|
304
|
+
{...baseProps}
|
|
305
305
|
hasChildren={false}
|
|
306
306
|
/>
|
|
307
307
|
);
|
|
@@ -310,27 +310,27 @@ describe('[component] ExpandButtonMinimal', () => {
|
|
|
310
310
|
});
|
|
311
311
|
|
|
312
312
|
it('renders button when hasChildren is true', () => {
|
|
313
|
-
render(<ExpandButtonMinimal {...
|
|
313
|
+
render(<ExpandButtonMinimal {...baseProps} />);
|
|
314
314
|
|
|
315
315
|
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
316
316
|
});
|
|
317
317
|
|
|
318
318
|
it('renders minus sign when expanded', () => {
|
|
319
|
-
render(<ExpandButtonMinimal {...
|
|
319
|
+
render(<ExpandButtonMinimal {...baseProps} isExpanded={true} />);
|
|
320
320
|
|
|
321
321
|
expect(screen.getByText('−')).toBeInTheDocument();
|
|
322
322
|
expect(screen.queryByText('+')).not.toBeInTheDocument();
|
|
323
323
|
});
|
|
324
324
|
|
|
325
325
|
it('renders plus sign when not expanded', () => {
|
|
326
|
-
render(<ExpandButtonMinimal {...
|
|
326
|
+
render(<ExpandButtonMinimal {...baseProps} isExpanded={false} />);
|
|
327
327
|
|
|
328
328
|
expect(screen.getByText('+')).toBeInTheDocument();
|
|
329
329
|
expect(screen.queryByText('−')).not.toBeInTheDocument();
|
|
330
330
|
});
|
|
331
331
|
|
|
332
332
|
it('has correct testId attribute', () => {
|
|
333
|
-
render(<ExpandButtonMinimal {...
|
|
333
|
+
render(<ExpandButtonMinimal {...baseProps} rowId="test-row-456" />);
|
|
334
334
|
|
|
335
335
|
const button = screen.getByRole('button');
|
|
336
336
|
expect(button).toHaveAttribute('data-testid', 'expand-button-minimal-test-row-456');
|
|
@@ -344,7 +344,7 @@ describe('[component] ExpandButtonMinimal', () => {
|
|
|
344
344
|
|
|
345
345
|
render(
|
|
346
346
|
<ExpandButtonMinimal
|
|
347
|
-
{...
|
|
347
|
+
{...baseProps}
|
|
348
348
|
onClick={handleClick}
|
|
349
349
|
/>
|
|
350
350
|
);
|
|
@@ -361,7 +361,7 @@ describe('[component] ExpandButtonMinimal', () => {
|
|
|
361
361
|
|
|
362
362
|
render(
|
|
363
363
|
<ExpandButtonMinimal
|
|
364
|
-
{...
|
|
364
|
+
{...baseProps}
|
|
365
365
|
onClick={handleClick}
|
|
366
366
|
/>
|
|
367
367
|
);
|
|
@@ -379,7 +379,7 @@ describe('[component] ExpandButtonMinimal', () => {
|
|
|
379
379
|
|
|
380
380
|
render(
|
|
381
381
|
<ExpandButtonMinimal
|
|
382
|
-
{...
|
|
382
|
+
{...baseProps}
|
|
383
383
|
onClick={handleClick}
|
|
384
384
|
/>
|
|
385
385
|
);
|
|
@@ -399,7 +399,7 @@ describe('[component] ExpandButtonMinimal', () => {
|
|
|
399
399
|
render(
|
|
400
400
|
<div onClick={handleParentClick}>
|
|
401
401
|
<ExpandButtonMinimal
|
|
402
|
-
{...
|
|
402
|
+
{...baseProps}
|
|
403
403
|
onClick={handleClick}
|
|
404
404
|
/>
|
|
405
405
|
</div>
|
|
@@ -415,21 +415,21 @@ describe('[component] ExpandButtonMinimal', () => {
|
|
|
415
415
|
|
|
416
416
|
describe('Accessibility', () => {
|
|
417
417
|
it('has aria-label for collapsed state', () => {
|
|
418
|
-
render(<ExpandButtonMinimal {...
|
|
418
|
+
render(<ExpandButtonMinimal {...baseProps} isExpanded={false} />);
|
|
419
419
|
|
|
420
420
|
const button = screen.getByRole('button');
|
|
421
421
|
expect(button).toHaveAttribute('aria-label', 'Expand row');
|
|
422
422
|
});
|
|
423
423
|
|
|
424
424
|
it('has aria-label for expanded state', () => {
|
|
425
|
-
render(<ExpandButtonMinimal {...
|
|
425
|
+
render(<ExpandButtonMinimal {...baseProps} isExpanded={true} />);
|
|
426
426
|
|
|
427
427
|
const button = screen.getByRole('button');
|
|
428
428
|
expect(button).toHaveAttribute('aria-label', 'Collapse row');
|
|
429
429
|
});
|
|
430
430
|
|
|
431
431
|
it('has aria-expanded attribute', () => {
|
|
432
|
-
render(<ExpandButtonMinimal {...
|
|
432
|
+
render(<ExpandButtonMinimal {...baseProps} isExpanded={false} />);
|
|
433
433
|
|
|
434
434
|
const button = screen.getByRole('button');
|
|
435
435
|
expect(button).toHaveAttribute('aria-expanded', 'false');
|
|
@@ -440,7 +440,7 @@ describe('[component] ExpandButtonMinimal', () => {
|
|
|
440
440
|
it('applies custom className', () => {
|
|
441
441
|
render(
|
|
442
442
|
<ExpandButtonMinimal
|
|
443
|
-
{...
|
|
443
|
+
{...baseProps}
|
|
444
444
|
className="custom-class"
|
|
445
445
|
/>
|
|
446
446
|
);
|
|
@@ -450,7 +450,7 @@ describe('[component] ExpandButtonMinimal', () => {
|
|
|
450
450
|
});
|
|
451
451
|
|
|
452
452
|
it('has proper button styling classes', () => {
|
|
453
|
-
render(<ExpandButtonMinimal {...
|
|
453
|
+
render(<ExpandButtonMinimal {...baseProps} />);
|
|
454
454
|
|
|
455
455
|
const button = screen.getByRole('button');
|
|
456
456
|
expect(button.className).toContain('inline-flex');
|