@jmruthers/pace-core 0.5.67 → 0.5.69
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/README.md +26 -0
- package/dist/{DataTable-MFUXNGPR.js → DataTable-MPBSXUC6.js} +5 -6
- package/dist/{PublicLoadingSpinner-DdKXTkCZ.d.ts → PublicLoadingSpinner-BOdyU3u-.d.ts} +1 -1
- package/dist/{UnifiedAuthProvider-CQNiemcB.d.ts → UnifiedAuthProvider-D02AMXgO.d.ts} +3 -3
- package/dist/{chunk-CKNY7HYS.js → chunk-2ARQW6VX.js} +3 -3
- package/dist/{chunk-T2MQY57J.js → chunk-6JILXFEA.js} +335 -5
- package/dist/chunk-6JILXFEA.js.map +1 -0
- package/dist/{chunk-D7ARGIA3.js → chunk-6RBH67W7.js} +23 -6
- package/dist/chunk-6RBH67W7.js.map +1 -0
- package/dist/{chunk-C7GUF747.js → chunk-FJTAWPAQ.js} +3 -5
- package/dist/{chunk-C7GUF747.js.map → chunk-FJTAWPAQ.js.map} +1 -1
- package/dist/{chunk-4HQ5BOVZ.js → chunk-NO5QHMDX.js} +7 -6
- package/dist/chunk-NO5QHMDX.js.map +1 -0
- package/dist/{chunk-ZPK5656W.js → chunk-O3NWNXDY.js} +4 -5
- package/dist/chunk-O3NWNXDY.js.map +1 -0
- package/dist/{chunk-BTCA3ENN.js → chunk-Q2UP3ZWQ.js} +4 -4
- package/dist/{chunk-QVEOQVD4.js → chunk-RVYGJPOD.js} +173 -20
- package/dist/chunk-RVYGJPOD.js.map +1 -0
- package/dist/{chunk-FVDOEGGG.js → chunk-UCMHBF7Y.js} +3 -5
- package/dist/{chunk-FVDOEGGG.js.map → chunk-UCMHBF7Y.js.map} +1 -1
- package/dist/{chunk-T6HVDA24.js → chunk-V3QO3LL7.js} +5 -7
- package/dist/chunk-V3QO3LL7.js.map +1 -0
- package/dist/{chunk-ZB6AEA7I.js → chunk-ZXJGZLLO.js} +17 -17
- package/dist/{chunk-ZB6AEA7I.js.map → chunk-ZXJGZLLO.js.map} +1 -1
- package/dist/components.d.ts +2 -2
- package/dist/components.js +8 -9
- package/dist/components.js.map +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +9 -6
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +16 -16
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +5 -7
- package/dist/rbac/index.js +5 -6
- package/dist/{usePublicRouteParams-CdoFxnJK.d.ts → usePublicRouteParams-Ua1Vz-HG.d.ts} +35 -1
- package/dist/utils.d.ts +4 -1
- package/dist/utils.js +3 -3
- package/docs/DOCUMENTATION_CHECKLIST.md +281 -0
- package/docs/README.md +22 -10
- package/docs/api/README.md +26 -0
- 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/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.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/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventContextType.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/EventProviderProps.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- 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 +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +2 -2
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContextType.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACProviderProps.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.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/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +4 -4
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +39 -14
- package/docs/api-reference/providers.md +16 -7
- package/docs/architecture/services.md +374 -0
- package/docs/best-practices/README.md +1 -1
- package/docs/best-practices/testing.md +1 -1
- package/docs/breaking-changes.md +182 -0
- package/docs/common-patterns.md +445 -0
- package/docs/core-concepts/authentication.md +26 -11
- package/docs/core-concepts/events.md +2 -0
- package/docs/core-concepts/organisations.md +2 -0
- package/docs/core-concepts/permissions.md +2 -0
- package/docs/{INDEX.md → documentation-index.md} +26 -38
- package/docs/faq.md +286 -0
- package/docs/{FILE_REFERENCE_SYSTEM.md → file-reference-system.md} +1 -1
- package/docs/getting-started/installation-guide.md +284 -0
- package/docs/getting-started/quick-start.md +8 -1
- package/docs/implementation-guides/app-layout.md +3 -1
- package/docs/implementation-guides/data-tables.md +2 -0
- package/docs/implementation-guides/dynamic-colors.md +47 -2
- package/docs/implementation-guides/event-theming-summary.md +220 -0
- package/docs/implementation-guides/forms.md +9 -7
- package/docs/implementation-guides/navigation.md +2 -0
- package/docs/migration/service-architecture.md +351 -0
- package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +226 -0
- package/docs/rbac/README-rbac-rls-integration.md +2 -2
- package/docs/rbac/README.md +1 -1
- package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
- package/docs/rbac/quick-start.md +2 -0
- package/docs/rbac/rbac-rls-integration.md +2 -2
- package/docs/security/README.md +5 -1
- package/docs/style-guide.md +136 -1
- package/docs/testing/README.md +1 -1
- package/docs/troubleshooting/authentication-issues.md +334 -0
- package/docs/troubleshooting/common-issues.md +2 -0
- package/docs/troubleshooting/styling-issues.md +199 -144
- package/docs/usage.md +23 -2
- package/package.json +1 -1
- package/src/__tests__/{TESTING_GUIDELINES.md → TEST_GUIDE_CURSOR.md} +20 -0
- package/src/__tests__/TEST_GUIDE_HUMAN.md +103 -0
- package/src/__tests__/fixtures/test-data.ts +90 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +260 -0
- package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +224 -0
- package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +273 -0
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +98 -0
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +436 -0
- package/src/__tests__/helpers/__tests__/timer-utils.test.ts +371 -0
- package/src/__tests__/helpers/component-test-utils.tsx +14 -4
- package/src/__tests__/helpers/optimized-test-setup.ts +68 -0
- package/src/__tests__/helpers/test-providers.tsx +329 -0
- package/src/__tests__/helpers/test-utils.tsx +91 -45
- package/src/__tests__/helpers/timer-utils.ts +71 -0
- package/src/__tests__/hooks/usePermissions.test.ts +1 -5
- package/src/__tests__/integration/UserProfile.test.tsx +1 -5
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +42 -12
- package/src/__tests__/setup.ts +34 -28
- package/src/components/Alert/Alert.test.tsx +1 -5
- package/src/components/Avatar/Avatar.test.tsx +1 -5
- package/src/components/Button/Button.test.tsx +4 -20
- package/src/components/Card/Card.test.tsx +1 -5
- package/src/components/Checkbox/Checkbox.test.tsx +1 -5
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -5
- package/src/components/DataTable/__tests__/DataTable.test.tsx +45 -49
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +1 -5
- package/src/components/DataTable/__tests__/styles.test.ts +382 -0
- package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +409 -0
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +634 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +519 -0
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +714 -0
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +592 -0
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +354 -0
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +539 -0
- package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +1 -5
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +1 -8
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +34 -38
- package/src/components/Footer/Footer.test.tsx +1 -5
- package/src/components/Form/Form.test.tsx +22 -35
- package/src/components/Header/Header.test.tsx +1 -9
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +1 -5
- package/src/components/Input/Input.test.tsx +2 -10
- package/src/components/LoginForm/LoginForm.test.tsx +1 -5
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +24 -24
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +1 -6
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -16
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +1 -5
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +1 -5
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +1 -7
- package/src/components/PasswordReset/PasswordChangeForm.test.tsx +1 -9
- package/src/components/PasswordReset/PasswordResetForm.test.tsx +1 -9
- package/src/components/PublicLayout/PublicErrorBoundary.tsx +4 -5
- package/src/components/PublicLayout/PublicPageHeader.tsx +13 -9
- package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +666 -0
- package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +457 -0
- package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +393 -0
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +351 -0
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +374 -0
- package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +388 -0
- package/src/components/Select/Select.bug-test.tsx +69 -0
- package/src/components/Select/Select.refactored.tsx +497 -0
- package/src/components/Select/Select.test.tsx +42 -49
- package/src/components/Select/Select.tsx +5 -2
- package/src/components/Select/hooks.ts +254 -0
- package/src/components/Switch/Switch.test.tsx +1 -5
- package/src/components/Table/__tests__/Table.test.tsx +775 -0
- package/src/components/Toast/Toast.test.tsx +15 -8
- package/src/components/Tooltip/Tooltip.test.tsx +1 -5
- package/src/components/UserMenu/UserMenu.test.tsx +3 -15
- package/src/components/__tests__/FileDisplay.test.tsx +575 -0
- package/src/components/__tests__/FileUpload.test.tsx +446 -0
- package/src/components/__tests__/SuperAdminGuard.test.tsx +422 -354
- package/src/hooks/__tests__/ServiceHooks.test.tsx +613 -0
- package/src/hooks/__tests__/hooks.integration.test.tsx +1 -10
- package/src/hooks/__tests__/useApiFetch.unit.test.ts +10 -14
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +307 -0
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +1 -6
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +1 -5
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +6 -9
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +321 -0
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +583 -0
- package/src/hooks/__tests__/usePublicEventLogo.unit.test.ts +640 -0
- package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +435 -0
- package/src/hooks/__tests__/useRBAC.unit.test.ts +10 -10
- package/src/hooks/__tests__/useStorage.unit.test.ts +751 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/public/usePublicEvent.ts +181 -13
- package/src/hooks/public/usePublicRouteParams.ts +13 -3
- package/src/hooks/services/useAuth.ts +50 -0
- package/src/hooks/services/useAuthService.ts +30 -0
- package/src/hooks/services/useCurrentEvent.ts +36 -0
- package/src/hooks/services/useCurrentOrganisation.ts +52 -0
- package/src/hooks/services/useEventService.ts +30 -0
- package/src/hooks/services/useInactivityService.ts +30 -0
- package/src/hooks/services/useOrganisationService.ts +30 -0
- package/src/hooks/services/usePermissions.ts +70 -0
- package/src/hooks/services/useRBACService.ts +30 -0
- package/src/hooks/useCounter.test.ts +1 -5
- package/src/hooks/useEventTheme.ts +86 -0
- package/src/hooks/useOrganisationPermissions.test.ts +2 -5
- package/src/hooks/useOrganisationSecurity.test.ts +1 -5
- package/src/hooks/usePermissionCache.test.ts +1 -5
- package/src/hooks/usePermissionCheck.ts +150 -0
- package/src/hooks/useSecureDataAccess.test.ts +1 -5
- package/src/index.ts +1 -0
- package/src/providers/OrganisationProvider.test.tsx +1 -5
- package/src/providers/OrganisationProvider.tsx +56 -4
- package/src/providers/UnifiedAuthProvider.test.simple.tsx +42 -6
- package/src/providers/UnifiedAuthProvider.test.tsx +1 -5
- package/src/providers/UnifiedAuthProvider.tsx +4 -4
- package/src/providers/__tests__/AuthProvider.test.tsx +105 -439
- package/src/providers/__tests__/AuthProvider.test.tsx.backup +771 -0
- package/src/providers/__tests__/EventProvider.test.tsx +211 -110
- package/src/providers/__tests__/EventProvider.test.tsx.backup +824 -0
- package/src/providers/__tests__/InactivityProvider.test.tsx +1 -5
- package/src/providers/__tests__/OrganisationProvider.test.tsx +97 -261
- package/src/providers/__tests__/OrganisationProvider.test.tsx.backup +820 -0
- package/src/providers/__tests__/ServiceProviders.test.tsx +477 -0
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +72 -504
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup +911 -0
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup2 +166 -0
- package/src/providers/services/AuthServiceProvider.tsx +65 -0
- package/src/providers/services/EventServiceProvider.tsx +83 -0
- package/src/providers/services/InactivityServiceProvider.tsx +83 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +77 -0
- package/src/providers/services/RBACServiceProvider.tsx +79 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +368 -0
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +210 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +269 -0
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +892 -0
- package/src/rbac/__tests__/engine.comprehensive.test.ts +954 -0
- package/src/rbac/__tests__/integration.authflow.test.tsx +1 -5
- package/src/rbac/__tests__/integration.navigation.test.tsx +1 -4
- package/src/rbac/__tests__/rbac-core.test.tsx +2 -7
- package/src/rbac/__tests__/rbac-functions.test.ts +1 -9
- package/src/rbac/__tests__/rbac-integration.test.ts +1 -9
- package/src/rbac/api.test.ts +1 -9
- package/src/rbac/cache.test.ts +10 -8
- package/src/rbac/cli/__tests__/policy-manager.test.ts +339 -0
- package/src/rbac/components/EnhancedNavigationMenu.test.tsx +1 -5
- package/src/rbac/components/NavigationProvider.test.tsx +1 -5
- package/src/rbac/components/PagePermissionProvider.test.tsx +1 -5
- package/src/rbac/components/SecureDataProvider.test.tsx +1 -5
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +25 -29
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +27 -30
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +23 -27
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +18 -22
- package/src/rbac/config.test.ts +1 -5
- package/src/rbac/hooks/useCan.test.ts +262 -9
- package/src/rbac/hooks/usePermissions.test.ts +246 -6
- package/src/rbac/hooks/useRBAC.simple.test.ts +1 -5
- package/src/rbac/hooks/useRBAC.test.ts +472 -198
- package/src/rbac/providers/__tests__/RBACProvider.test.tsx +1 -9
- package/src/services/AuthService.ts +416 -0
- package/src/services/EventService.ts +366 -0
- package/src/services/InactivityService.ts +388 -0
- package/src/services/OrganisationService.ts +592 -0
- package/src/services/RBACService.ts +522 -0
- package/src/services/__tests__/AuthService.test.ts +356 -0
- package/src/services/__tests__/BaseService.test.ts +314 -0
- package/src/services/__tests__/EventService.test.ts +489 -0
- package/src/services/__tests__/InactivityService.test.ts +403 -0
- package/src/services/__tests__/OrganisationService.test.ts +660 -0
- package/src/services/__tests__/RBACService.test.ts +492 -0
- package/src/services/base/BaseService.ts +87 -0
- package/src/services/interfaces/IAuthService.ts +39 -0
- package/src/services/interfaces/IEventService.ts +30 -0
- package/src/services/interfaces/IInactivityService.ts +31 -0
- package/src/services/interfaces/IOrganisationService.ts +41 -0
- package/src/services/interfaces/IRBACService.ts +62 -0
- package/src/theming/__tests__/runtime.test.ts +540 -0
- package/src/types/__tests__/file-reference.test.ts +447 -0
- package/src/types/__tests__/organisation.test.ts +1133 -0
- package/src/types/__tests__/theme.test.ts +830 -0
- package/src/types/__tests__/type-validation.test.ts +527 -0
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +1 -5
- package/src/utils/__tests__/debugLogger.test.ts +417 -0
- package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -6
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -5
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +35 -35
- package/src/utils/__tests__/organisationContext.unit.test.ts +1 -5
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +5 -11
- package/src/utils/__tests__/secureErrors.unit.test.ts +1 -6
- package/src/utils/__tests__/secureStorage.unit.test.ts +1 -5
- package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -5
- package/src/utils/__tests__/sessionTracking.unit.test.ts +1 -5
- package/src/utils/appIdResolver.test.ts +6 -10
- package/src/utils/appNameResolver.simple.test.ts +142 -0
- package/src/utils/appNameResolver.test.ts +31 -458
- package/src/utils/appNameResolver.test.ts.backup +494 -0
- package/src/utils/debugLogger.ts +26 -5
- package/src/utils/formatDate.test.ts +1 -5
- package/src/utils/organisationContext.test.ts +1 -5
- package/src/utils/performanceBudgets.ts +3 -4
- package/src/utils/secureDataAccess.test.ts +1 -5
- package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -5
- package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +1 -5
- package/dist/chunk-4HQ5BOVZ.js.map +0 -1
- package/dist/chunk-D7ARGIA3.js.map +0 -1
- package/dist/chunk-QVEOQVD4.js.map +0 -1
- package/dist/chunk-T2MQY57J.js.map +0 -1
- package/dist/chunk-T6HVDA24.js.map +0 -1
- package/dist/chunk-VTJ5HCZB.js +0 -315
- package/dist/chunk-VTJ5HCZB.js.map +0 -1
- package/dist/chunk-ZPK5656W.js.map +0 -1
- package/docs/getting-started/installation.md +0 -269
- package/src/__tests__/REBUILD_PLAN.md +0 -223
- /package/dist/{DataTable-MFUXNGPR.js.map → DataTable-MPBSXUC6.js.map} +0 -0
- /package/dist/{chunk-CKNY7HYS.js.map → chunk-2ARQW6VX.js.map} +0 -0
- /package/dist/{chunk-BTCA3ENN.js.map → chunk-Q2UP3ZWQ.js.map} +0 -0
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file DataManager Unit Tests
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Components/DataTable/Core/DataManager
|
|
5
|
+
* @since 0.3.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
|
9
|
+
import { DataManager } from '../DataManager';
|
|
10
|
+
import type { DataAdapter, FetchOptions } from '../interfaces';
|
|
11
|
+
import type { DataRecord } from '../../types';
|
|
12
|
+
|
|
13
|
+
// Test data types
|
|
14
|
+
interface TestDataRecord extends DataRecord {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
email: string;
|
|
18
|
+
created_at: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Mock data adapter
|
|
22
|
+
const createMockAdapter = (): DataAdapter<TestDataRecord> => ({
|
|
23
|
+
name: 'test-adapter',
|
|
24
|
+
fetchData: vi.fn(),
|
|
25
|
+
updateData: vi.fn(),
|
|
26
|
+
deleteData: vi.fn(),
|
|
27
|
+
createData: vi.fn(),
|
|
28
|
+
exportData: vi.fn(),
|
|
29
|
+
importData: vi.fn(),
|
|
30
|
+
isConnected: vi.fn(() => true),
|
|
31
|
+
getError: vi.fn(() => null),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Test data fixtures
|
|
35
|
+
const createTestData = (overrides: Partial<TestDataRecord> = {}): TestDataRecord => ({
|
|
36
|
+
id: 'test-id-1',
|
|
37
|
+
name: 'Test User',
|
|
38
|
+
email: 'test@example.com',
|
|
39
|
+
created_at: '2023-01-01T00:00:00Z',
|
|
40
|
+
...overrides,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const createTestDataArray = (count: number): TestDataRecord[] =>
|
|
44
|
+
Array.from({ length: count }, (_, i) => createTestData({
|
|
45
|
+
id: `test-id-${i + 1}`,
|
|
46
|
+
name: `Test User ${i + 1}`,
|
|
47
|
+
email: `test${i + 1}@example.com`,
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
describe('[unit] DataManager', () => {
|
|
51
|
+
let dataManager: DataManager<TestDataRecord>;
|
|
52
|
+
let mockAdapter: DataAdapter<TestDataRecord>;
|
|
53
|
+
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
mockAdapter = createMockAdapter();
|
|
56
|
+
dataManager = new DataManager(mockAdapter, 5000); // 5 second cache timeout
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
afterEach(() => {
|
|
60
|
+
vi.clearAllMocks();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('Initialization', () => {
|
|
64
|
+
it('should initialize with empty data and default state', () => {
|
|
65
|
+
expect(dataManager.getData()).toEqual([]);
|
|
66
|
+
expect(dataManager.isLoading()).toBe(false);
|
|
67
|
+
expect(dataManager.getError()).toBe(null);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should initialize with custom cache timeout', () => {
|
|
71
|
+
const customTimeout = 10000;
|
|
72
|
+
const manager = new DataManager(mockAdapter, customTimeout);
|
|
73
|
+
expect(manager).toBeDefined();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should set adapter correctly', () => {
|
|
77
|
+
expect(dataManager.getAdapter()).toBe(mockAdapter);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('Data Retrieval', () => {
|
|
82
|
+
it('should return current data', () => {
|
|
83
|
+
const testData = createTestDataArray(3);
|
|
84
|
+
// Manually set data for testing (simulating internal state)
|
|
85
|
+
(dataManager as any).data = testData;
|
|
86
|
+
|
|
87
|
+
expect(dataManager.getData()).toEqual(testData);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should return empty array when no data', () => {
|
|
91
|
+
expect(dataManager.getData()).toEqual([]);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe('CRUD Operations', () => {
|
|
96
|
+
describe('Create Data', () => {
|
|
97
|
+
it('should create new data item successfully', async () => {
|
|
98
|
+
const newData = { name: 'New User', email: 'new@example.com' };
|
|
99
|
+
const createdItem = createTestData(newData);
|
|
100
|
+
|
|
101
|
+
vi.mocked(mockAdapter.createData).mockResolvedValue(createdItem);
|
|
102
|
+
|
|
103
|
+
const result = await dataManager.createData(newData);
|
|
104
|
+
|
|
105
|
+
expect(mockAdapter.createData).toHaveBeenCalledWith(newData);
|
|
106
|
+
expect(result).toEqual(createdItem);
|
|
107
|
+
expect(dataManager.getData()).toContain(createdItem);
|
|
108
|
+
expect(dataManager.isLoading()).toBe(false);
|
|
109
|
+
expect(dataManager.getError()).toBe(null);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should handle create data errors', async () => {
|
|
113
|
+
const newData = { name: 'New User', email: 'new@example.com' };
|
|
114
|
+
const error = new Error('Create failed');
|
|
115
|
+
|
|
116
|
+
vi.mocked(mockAdapter.createData).mockRejectedValue(error);
|
|
117
|
+
|
|
118
|
+
await expect(dataManager.createData(newData)).rejects.toThrow('Create failed');
|
|
119
|
+
|
|
120
|
+
expect(dataManager.getError()).toBe(error);
|
|
121
|
+
expect(dataManager.isLoading()).toBe(false);
|
|
122
|
+
expect(dataManager.getData()).toEqual([]);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should set loading state during create operation', async () => {
|
|
126
|
+
const newData = { name: 'New User', email: 'new@example.com' };
|
|
127
|
+
const createdItem = createTestData(newData);
|
|
128
|
+
|
|
129
|
+
let resolveCreate: (value: TestDataRecord) => void;
|
|
130
|
+
const createPromise = new Promise<TestDataRecord>((resolve) => {
|
|
131
|
+
resolveCreate = resolve;
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
vi.mocked(mockAdapter.createData).mockReturnValue(createPromise);
|
|
135
|
+
|
|
136
|
+
const createPromise2 = dataManager.createData(newData);
|
|
137
|
+
|
|
138
|
+
// Check loading state during operation
|
|
139
|
+
expect(dataManager.isLoading()).toBe(true);
|
|
140
|
+
|
|
141
|
+
resolveCreate!(createdItem);
|
|
142
|
+
await createPromise2;
|
|
143
|
+
|
|
144
|
+
expect(dataManager.isLoading()).toBe(false);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('Update Data', () => {
|
|
149
|
+
beforeEach(() => {
|
|
150
|
+
// Set up initial data
|
|
151
|
+
const testData = createTestDataArray(3);
|
|
152
|
+
(dataManager as any).data = testData;
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should update existing data item successfully', async () => {
|
|
156
|
+
const id = 'test-id-1';
|
|
157
|
+
const updates = { name: 'Updated User' };
|
|
158
|
+
|
|
159
|
+
vi.mocked(mockAdapter.updateData).mockResolvedValue(undefined);
|
|
160
|
+
|
|
161
|
+
await dataManager.updateData(id, updates);
|
|
162
|
+
|
|
163
|
+
expect(mockAdapter.updateData).toHaveBeenCalledWith(id, updates);
|
|
164
|
+
|
|
165
|
+
const updatedItem = dataManager.getData().find(item => item.id === id);
|
|
166
|
+
expect(updatedItem).toMatchObject(updates);
|
|
167
|
+
expect(dataManager.isLoading()).toBe(false);
|
|
168
|
+
expect(dataManager.getError()).toBe(null);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should handle update data errors', async () => {
|
|
172
|
+
const id = 'test-id-1';
|
|
173
|
+
const updates = { name: 'Updated User' };
|
|
174
|
+
const error = new Error('Update failed');
|
|
175
|
+
|
|
176
|
+
vi.mocked(mockAdapter.updateData).mockRejectedValue(error);
|
|
177
|
+
|
|
178
|
+
await expect(dataManager.updateData(id, updates)).rejects.toThrow('Update failed');
|
|
179
|
+
|
|
180
|
+
expect(dataManager.getError()).toBe(error);
|
|
181
|
+
expect(dataManager.isLoading()).toBe(false);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should not update local data if item not found', async () => {
|
|
185
|
+
const id = 'non-existent-id';
|
|
186
|
+
const updates = { name: 'Updated User' };
|
|
187
|
+
|
|
188
|
+
vi.mocked(mockAdapter.updateData).mockResolvedValue(undefined);
|
|
189
|
+
|
|
190
|
+
await dataManager.updateData(id, updates);
|
|
191
|
+
|
|
192
|
+
expect(mockAdapter.updateData).toHaveBeenCalledWith(id, updates);
|
|
193
|
+
// Local data should remain unchanged
|
|
194
|
+
expect(dataManager.getData()).toEqual(createTestDataArray(3));
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('should set loading state during update operation', async () => {
|
|
198
|
+
const id = 'test-id-1';
|
|
199
|
+
const updates = { name: 'Updated User' };
|
|
200
|
+
|
|
201
|
+
let resolveUpdate: () => void;
|
|
202
|
+
const updatePromise = new Promise<void>((resolve) => {
|
|
203
|
+
resolveUpdate = resolve;
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
vi.mocked(mockAdapter.updateData).mockReturnValue(updatePromise);
|
|
207
|
+
|
|
208
|
+
const updatePromise2 = dataManager.updateData(id, updates);
|
|
209
|
+
|
|
210
|
+
// Check loading state during operation
|
|
211
|
+
expect(dataManager.isLoading()).toBe(true);
|
|
212
|
+
|
|
213
|
+
resolveUpdate!();
|
|
214
|
+
await updatePromise2;
|
|
215
|
+
|
|
216
|
+
expect(dataManager.isLoading()).toBe(false);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
describe('Delete Data', () => {
|
|
221
|
+
beforeEach(() => {
|
|
222
|
+
// Set up initial data
|
|
223
|
+
const testData = createTestDataArray(3);
|
|
224
|
+
(dataManager as any).data = testData;
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should delete data item successfully', async () => {
|
|
228
|
+
const id = 'test-id-1';
|
|
229
|
+
|
|
230
|
+
vi.mocked(mockAdapter.deleteData).mockResolvedValue(undefined);
|
|
231
|
+
|
|
232
|
+
await dataManager.deleteData(id);
|
|
233
|
+
|
|
234
|
+
expect(mockAdapter.deleteData).toHaveBeenCalledWith(id);
|
|
235
|
+
expect(dataManager.getData()).toHaveLength(2);
|
|
236
|
+
expect(dataManager.getData().find(item => item.id === id)).toBeUndefined();
|
|
237
|
+
expect(dataManager.isLoading()).toBe(false);
|
|
238
|
+
expect(dataManager.getError()).toBe(null);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('should handle delete data errors', async () => {
|
|
242
|
+
const id = 'test-id-1';
|
|
243
|
+
const error = new Error('Delete failed');
|
|
244
|
+
|
|
245
|
+
vi.mocked(mockAdapter.deleteData).mockRejectedValue(error);
|
|
246
|
+
|
|
247
|
+
await expect(dataManager.deleteData(id)).rejects.toThrow('Delete failed');
|
|
248
|
+
|
|
249
|
+
expect(dataManager.getError()).toBe(error);
|
|
250
|
+
expect(dataManager.isLoading()).toBe(false);
|
|
251
|
+
// Data should remain unchanged on error
|
|
252
|
+
expect(dataManager.getData()).toHaveLength(3);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('should not remove item if not found locally', async () => {
|
|
256
|
+
const id = 'non-existent-id';
|
|
257
|
+
|
|
258
|
+
vi.mocked(mockAdapter.deleteData).mockResolvedValue(undefined);
|
|
259
|
+
|
|
260
|
+
await dataManager.deleteData(id);
|
|
261
|
+
|
|
262
|
+
expect(mockAdapter.deleteData).toHaveBeenCalledWith(id);
|
|
263
|
+
// Local data should remain unchanged
|
|
264
|
+
expect(dataManager.getData()).toHaveLength(3);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should set loading state during delete operation', async () => {
|
|
268
|
+
const id = 'test-id-1';
|
|
269
|
+
|
|
270
|
+
let resolveDelete: () => void;
|
|
271
|
+
const deletePromise = new Promise<void>((resolve) => {
|
|
272
|
+
resolveDelete = resolve;
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
vi.mocked(mockAdapter.deleteData).mockReturnValue(deletePromise);
|
|
276
|
+
|
|
277
|
+
const deletePromise2 = dataManager.deleteData(id);
|
|
278
|
+
|
|
279
|
+
// Check loading state during operation
|
|
280
|
+
expect(dataManager.isLoading()).toBe(true);
|
|
281
|
+
|
|
282
|
+
resolveDelete!();
|
|
283
|
+
await deletePromise2;
|
|
284
|
+
|
|
285
|
+
expect(dataManager.isLoading()).toBe(false);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
describe('Caching', () => {
|
|
291
|
+
it('should cache data with timestamp', async () => {
|
|
292
|
+
const cacheKey = 'test-cache-key';
|
|
293
|
+
const testData = createTestDataArray(3);
|
|
294
|
+
|
|
295
|
+
dataManager.setCachedData(cacheKey, testData);
|
|
296
|
+
|
|
297
|
+
const cachedData = await dataManager.getCachedData(cacheKey);
|
|
298
|
+
expect(cachedData).toEqual(testData);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('should return null for non-existent cache key', async () => {
|
|
302
|
+
const cacheKey = 'non-existent-key';
|
|
303
|
+
|
|
304
|
+
const cachedData = await dataManager.getCachedData(cacheKey);
|
|
305
|
+
expect(cachedData).toBeNull();
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('should return null for expired cache', async () => {
|
|
309
|
+
const cacheKey = 'expired-cache-key';
|
|
310
|
+
const testData = createTestDataArray(3);
|
|
311
|
+
|
|
312
|
+
// Set cache with old timestamp
|
|
313
|
+
(dataManager as any).cache.set(cacheKey, {
|
|
314
|
+
data: testData,
|
|
315
|
+
timestamp: Date.now() - 10000, // 10 seconds ago
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
const cachedData = await dataManager.getCachedData(cacheKey);
|
|
319
|
+
expect(cachedData).toBeNull();
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it('should clear cache after CRUD operations', async () => {
|
|
323
|
+
const cacheKey = 'test-cache-key';
|
|
324
|
+
const testData = createTestDataArray(3);
|
|
325
|
+
|
|
326
|
+
dataManager.setCachedData(cacheKey, testData);
|
|
327
|
+
expect(await dataManager.getCachedData(cacheKey)).toEqual(testData);
|
|
328
|
+
|
|
329
|
+
// Perform CRUD operation
|
|
330
|
+
const newData = { name: 'New User', email: 'new@example.com' };
|
|
331
|
+
const createdItem = createTestData(newData);
|
|
332
|
+
vi.mocked(mockAdapter.createData).mockResolvedValue(createdItem);
|
|
333
|
+
|
|
334
|
+
await dataManager.createData(newData);
|
|
335
|
+
|
|
336
|
+
// Cache should be cleared
|
|
337
|
+
expect(await dataManager.getCachedData(cacheKey)).toBeNull();
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('should clear all cache', () => {
|
|
341
|
+
const testData = createTestDataArray(3);
|
|
342
|
+
|
|
343
|
+
dataManager.setCachedData('key1', testData);
|
|
344
|
+
dataManager.setCachedData('key2', testData);
|
|
345
|
+
|
|
346
|
+
expect((dataManager as any).cache.size).toBe(2);
|
|
347
|
+
|
|
348
|
+
dataManager.clearCache();
|
|
349
|
+
|
|
350
|
+
expect((dataManager as any).cache.size).toBe(0);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it('should handle cache timeout configuration', async () => {
|
|
354
|
+
const shortTimeoutManager = new DataManager(mockAdapter, 1000); // 1 second timeout
|
|
355
|
+
const cacheKey = 'test-cache-key';
|
|
356
|
+
const testData = createTestDataArray(3);
|
|
357
|
+
|
|
358
|
+
shortTimeoutManager.setCachedData(cacheKey, testData);
|
|
359
|
+
|
|
360
|
+
// Should be available immediately
|
|
361
|
+
expect(await shortTimeoutManager.getCachedData(cacheKey)).toEqual(testData);
|
|
362
|
+
|
|
363
|
+
// Wait for timeout
|
|
364
|
+
await new Promise(resolve => setTimeout(resolve, 1100));
|
|
365
|
+
|
|
366
|
+
// Should be expired now
|
|
367
|
+
expect(await shortTimeoutManager.getCachedData(cacheKey)).toBeNull();
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
describe('Error Handling', () => {
|
|
372
|
+
it('should set error state on create failure', async () => {
|
|
373
|
+
const error = new Error('Create failed');
|
|
374
|
+
vi.mocked(mockAdapter.createData).mockRejectedValue(error);
|
|
375
|
+
|
|
376
|
+
await expect(dataManager.createData({})).rejects.toThrow();
|
|
377
|
+
expect(dataManager.getError()).toBe(error);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it('should set error state on update failure', async () => {
|
|
381
|
+
const error = new Error('Update failed');
|
|
382
|
+
vi.mocked(mockAdapter.updateData).mockRejectedValue(error);
|
|
383
|
+
|
|
384
|
+
await expect(dataManager.updateData('id', {})).rejects.toThrow();
|
|
385
|
+
expect(dataManager.getError()).toBe(error);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it('should set error state on delete failure', async () => {
|
|
389
|
+
const error = new Error('Delete failed');
|
|
390
|
+
vi.mocked(mockAdapter.deleteData).mockRejectedValue(error);
|
|
391
|
+
|
|
392
|
+
await expect(dataManager.deleteData('id')).rejects.toThrow();
|
|
393
|
+
expect(dataManager.getError()).toBe(error);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it('should clear error state on successful operation', async () => {
|
|
397
|
+
// First, set an error
|
|
398
|
+
const error = new Error('Previous error');
|
|
399
|
+
(dataManager as any).error = error;
|
|
400
|
+
expect(dataManager.getError()).toBe(error);
|
|
401
|
+
|
|
402
|
+
// Then perform successful operation
|
|
403
|
+
const newData = { name: 'New User', email: 'new@example.com' };
|
|
404
|
+
const createdItem = createTestData(newData);
|
|
405
|
+
vi.mocked(mockAdapter.createData).mockResolvedValue(createdItem);
|
|
406
|
+
|
|
407
|
+
await dataManager.createData(newData);
|
|
408
|
+
|
|
409
|
+
expect(dataManager.getError()).toBe(null);
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
describe('Adapter Management', () => {
|
|
414
|
+
it('should set new adapter', () => {
|
|
415
|
+
const newAdapter = createMockAdapter();
|
|
416
|
+
|
|
417
|
+
dataManager.setAdapter(newAdapter);
|
|
418
|
+
|
|
419
|
+
expect(dataManager.getAdapter()).toBe(newAdapter);
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it('should clear cache when setting new adapter', () => {
|
|
423
|
+
const testData = createTestDataArray(3);
|
|
424
|
+
dataManager.setCachedData('test-key', testData);
|
|
425
|
+
|
|
426
|
+
expect((dataManager as any).cache.size).toBe(1);
|
|
427
|
+
|
|
428
|
+
const newAdapter = createMockAdapter();
|
|
429
|
+
dataManager.setAdapter(newAdapter);
|
|
430
|
+
|
|
431
|
+
expect((dataManager as any).cache.size).toBe(0);
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
describe('Row ID Generation', () => {
|
|
436
|
+
it('should use id field for row identification', () => {
|
|
437
|
+
const item = createTestData({ id: 'test-id' });
|
|
438
|
+
const rowId = (dataManager as any).getRowId(item);
|
|
439
|
+
expect(rowId).toBe('test-id');
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
it('should use key field when id is not available', () => {
|
|
443
|
+
const item = { key: 'test-key', name: 'Test' } as any;
|
|
444
|
+
const rowId = (dataManager as any).getRowId(item);
|
|
445
|
+
expect(rowId).toBe('test-key');
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
it('should use JSON string when neither id nor key is available', () => {
|
|
449
|
+
const item = { name: 'Test', email: 'test@example.com' } as any;
|
|
450
|
+
const rowId = (dataManager as any).getRowId(item);
|
|
451
|
+
expect(rowId).toBe(JSON.stringify(item));
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
describe('Concurrent Operations', () => {
|
|
456
|
+
it('should handle concurrent create operations', async () => {
|
|
457
|
+
const data1 = { name: 'User 1', email: 'user1@example.com' };
|
|
458
|
+
const data2 = { name: 'User 2', email: 'user2@example.com' };
|
|
459
|
+
const created1 = createTestData({ ...data1, id: 'id-1' });
|
|
460
|
+
const created2 = createTestData({ ...data2, id: 'id-2' });
|
|
461
|
+
|
|
462
|
+
vi.mocked(mockAdapter.createData)
|
|
463
|
+
.mockResolvedValueOnce(created1)
|
|
464
|
+
.mockResolvedValueOnce(created2);
|
|
465
|
+
|
|
466
|
+
const [result1, result2] = await Promise.all([
|
|
467
|
+
dataManager.createData(data1),
|
|
468
|
+
dataManager.createData(data2),
|
|
469
|
+
]);
|
|
470
|
+
|
|
471
|
+
expect(result1).toEqual(created1);
|
|
472
|
+
expect(result2).toEqual(created2);
|
|
473
|
+
expect(dataManager.getData()).toHaveLength(2);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
it('should handle concurrent update operations', async () => {
|
|
477
|
+
const testData = createTestDataArray(2);
|
|
478
|
+
(dataManager as any).data = testData;
|
|
479
|
+
|
|
480
|
+
vi.mocked(mockAdapter.updateData).mockResolvedValue(undefined);
|
|
481
|
+
|
|
482
|
+
await Promise.all([
|
|
483
|
+
dataManager.updateData('test-id-1', { name: 'Updated 1' }),
|
|
484
|
+
dataManager.updateData('test-id-2', { name: 'Updated 2' }),
|
|
485
|
+
]);
|
|
486
|
+
|
|
487
|
+
expect(mockAdapter.updateData).toHaveBeenCalledTimes(2);
|
|
488
|
+
expect(dataManager.getData()).toHaveLength(2);
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
describe('Performance and Memory', () => {
|
|
493
|
+
it('should handle large datasets efficiently', async () => {
|
|
494
|
+
const largeDataset = createTestDataArray(1000);
|
|
495
|
+
(dataManager as any).data = largeDataset;
|
|
496
|
+
|
|
497
|
+
expect(dataManager.getData()).toHaveLength(1000);
|
|
498
|
+
expect(dataManager.getData()[0]).toEqual(expect.objectContaining({
|
|
499
|
+
id: 'test-id-1',
|
|
500
|
+
name: 'Test User 1',
|
|
501
|
+
}));
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it('should not leak memory with repeated operations', async () => {
|
|
505
|
+
const testData = { name: 'Test User', email: 'test@example.com' };
|
|
506
|
+
const createdItem = createTestData(testData);
|
|
507
|
+
|
|
508
|
+
vi.mocked(mockAdapter.createData).mockResolvedValue(createdItem);
|
|
509
|
+
|
|
510
|
+
// Perform multiple operations
|
|
511
|
+
for (let i = 0; i < 100; i++) {
|
|
512
|
+
await dataManager.createData({ ...testData, name: `User ${i}` });
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
expect(dataManager.getData()).toHaveLength(100);
|
|
516
|
+
expect((dataManager as any).cache.size).toBe(0); // Cache should be cleared after each operation
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
});
|