@jmruthers/pace-core 0.5.180 → 0.5.182
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 +1 -1
- package/README.md +16 -2
- package/dist/{AuthService-DYuQPJj6.d.ts → AuthService-B-cd2MA4.d.ts} +9 -11
- package/dist/{DataTable-CWAZZcXC.d.ts → DataTable-Bz8ffqyA.d.ts} +1 -1
- package/dist/{DataTable-4VSEJQ7D.js → DataTable-QAB34V6K.js} +14 -15
- package/dist/UnifiedAuthProvider-7F6T4B6K.js +13 -0
- package/dist/{UnifiedAuthProvider-DJxGTftH.d.ts → UnifiedAuthProvider-F86d7dSi.d.ts} +5 -6
- package/dist/{api-45XYYO2A.js → api-ROMBCNKU.js} +5 -5
- package/dist/{audit-64X3VJXB.js → audit-WRS3KJKI.js} +4 -4
- package/dist/auth-BZOJqrdd.d.ts +49 -0
- package/dist/{chunk-CX5M4ZAG.js → chunk-5DRSZLL2.js} +1 -1
- package/dist/chunk-5DRSZLL2.js.map +1 -0
- package/dist/{chunk-BESYRHQM.js → chunk-6C4YBBJM.js} +10 -7
- package/dist/chunk-6C4YBBJM.js.map +1 -0
- package/dist/{chunk-PLDDJCW6.js → chunk-7D4SUZUM.js} +2 -13
- package/dist/{chunk-6HLVGAZG.js → chunk-CSOFYHAG.js} +55 -162
- package/dist/chunk-CSOFYHAG.js.map +1 -0
- package/dist/{chunk-ANBQRTPX.js → chunk-E66EQZE6.js} +3 -5
- package/dist/{chunk-ANBQRTPX.js.map → chunk-E66EQZE6.js.map} +1 -1
- package/dist/{chunk-Q5QRDWKI.js → chunk-F2IMUDXZ.js} +4 -6
- package/dist/chunk-F2IMUDXZ.js.map +1 -0
- package/dist/{chunk-SBVILCCA.js → chunk-FSFQFJCU.js} +28 -6
- package/dist/chunk-FSFQFJCU.js.map +1 -0
- package/dist/chunk-FUEYYMX5.js +2296 -0
- package/dist/chunk-FUEYYMX5.js.map +1 -0
- package/dist/{chunk-FFKNH6U5.js → chunk-HKIT6O7W.js} +3 -5
- package/dist/{chunk-FFKNH6U5.js.map → chunk-HKIT6O7W.js.map} +1 -1
- package/dist/chunk-KQCRWDSA.js +1 -0
- package/dist/{chunk-S5OFRT4M.js → chunk-KUEN3HFB.js} +6 -6
- package/dist/chunk-KUEN3HFB.js.map +1 -0
- package/dist/chunk-LMC26NLJ.js +84 -0
- package/dist/chunk-LMC26NLJ.js.map +1 -0
- package/dist/{chunk-BVYWGZVV.js → chunk-M7W4CP3M.js} +52 -19
- package/dist/chunk-M7W4CP3M.js.map +1 -0
- package/dist/{chunk-CPTUD43C.js → chunk-MI7HBHN3.js} +164 -243
- package/dist/chunk-MI7HBHN3.js.map +1 -0
- package/dist/{chunk-N5YCCUG5.js → chunk-PWAHJW4G.js} +180 -29
- package/dist/chunk-PWAHJW4G.js.map +1 -0
- package/dist/chunk-PWLANIRT.js +127 -0
- package/dist/{chunk-XDNLUEXI.js.map → chunk-PWLANIRT.js.map} +1 -1
- package/dist/chunk-QCDXODCA.js +75 -0
- package/dist/chunk-QCDXODCA.js.map +1 -0
- package/dist/{chunk-P6UUHOIF.js → chunk-QETLRQI6.js} +526 -887
- package/dist/chunk-QETLRQI6.js.map +1 -0
- package/dist/{chunk-GQA2LIAE.js → chunk-QUVSNGIP.js} +264 -262
- package/dist/chunk-QUVSNGIP.js.map +1 -0
- package/dist/chunk-QXHPKYJV.js +113 -0
- package/dist/chunk-QXHPKYJV.js.map +1 -0
- package/dist/{chunk-OWAG3GSU.js → chunk-R77UEZ4E.js} +11 -1
- package/dist/chunk-R77UEZ4E.js.map +1 -0
- package/dist/{chunk-ONI7Y733.js → chunk-RA3JUFMW.js} +314 -161
- package/dist/chunk-RA3JUFMW.js.map +1 -0
- package/dist/{chunk-ERISIBYU.js → chunk-SQGMNID3.js} +3 -8
- package/dist/chunk-SQGMNID3.js.map +1 -0
- package/dist/{chunk-XJ2HZOBU.js → chunk-UHNYIBXL.js} +1 -1
- package/dist/chunk-UHNYIBXL.js.map +1 -0
- package/{src/utils/secureStorage.ts → dist/chunk-VBXEHIUJ.js} +113 -88
- package/dist/{chunk-7QCC6MCP.js.map → chunk-VBXEHIUJ.js.map} +1 -1
- package/dist/{chunk-R53TUSFK.js → chunk-W22JP75J.js} +5 -13
- package/dist/{chunk-R53TUSFK.js.map → chunk-W22JP75J.js.map} +1 -1
- package/dist/components.d.ts +12 -93
- package/dist/components.js +23 -106
- package/dist/components.js.map +1 -1
- package/dist/core-CUElvH_C.d.ts +164 -0
- package/dist/database.generated-CBmg2950.d.ts +8284 -0
- package/dist/event-CW5YB_2p.d.ts +239 -0
- package/dist/{file-reference-C6Gkn77H.d.ts → file-reference-D06mEEWW.d.ts} +7 -5
- package/dist/functions-D_kgHktt.d.ts +208 -0
- package/dist/hooks.d.ts +54 -7
- package/dist/hooks.js +204 -17
- package/dist/hooks.js.map +1 -1
- package/dist/{EventLogo-B3V3otev.d.ts → index-Bl--n7-T.d.ts} +387 -397
- package/dist/index.d.ts +94 -261
- package/dist/index.js +314 -126
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +7 -8
- package/dist/providers.js +6 -13
- package/dist/rbac/index.d.ts +171 -101
- package/dist/rbac/index.js +23 -17
- package/dist/styles/index.d.ts +1 -3
- package/dist/styles/index.js +2 -17
- package/dist/theming/runtime.js +3 -3
- package/dist/types-UU913iLA.d.ts +102 -0
- package/dist/{types-Dfz9dmVH.d.ts → types-_x1f4QBF.d.ts} +6 -6
- package/dist/types.d.ts +88 -227
- package/dist/types.js +64 -112
- package/dist/types.js.map +1 -1
- package/dist/{usePublicRouteParams-B7PabvuH.d.ts → usePublicRouteParams-JJczomYq.d.ts} +203 -6
- package/dist/utils.d.ts +299 -13
- package/dist/utils.js +481 -55
- package/dist/utils.js.map +1 -1
- package/dist/validation-643vUDZW.d.ts +177 -0
- package/docs/DOCUMENTATION_REVIEW_TRACKER.md +511 -0
- package/docs/README.md +9 -8
- package/docs/api/README.md +16 -2
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +4 -4
- package/docs/api/classes/MissingUserContextError.md +4 -4
- package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
- package/docs/api/classes/PermissionDeniedError.md +4 -4
- package/docs/api/classes/RBACAuditManager.md +14 -14
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +2 -2
- package/docs/api/classes/RBACError.md +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- package/docs/api/classes/SecureSupabaseClient.md +29 -9
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +17 -17
- package/docs/api/enums/RBACErrorCode.md +228 -0
- package/docs/api/enums/RPCFunction.md +118 -0
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +2 -2
- package/docs/api/interfaces/CalendarProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +29 -3
- 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/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +2 -2
- package/docs/api/interfaces/DataTableColumn.md +6 -6
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +2 -2
- 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 +5 -5
- package/docs/api/interfaces/ExportOptions.md +4 -4
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +13 -13
- package/docs/api/interfaces/FileReference.md +12 -12
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +10 -10
- package/docs/api/interfaces/FileUploadProps.md +19 -19
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +166 -0
- package/docs/api/interfaces/FormProps.md +113 -0
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +8 -8
- package/docs/api/interfaces/InputProps.md +2 -2
- package/docs/api/interfaces/LabelProps.md +8 -8
- 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 +17 -73
- package/docs/api/interfaces/NavigationMenuProps.md +38 -53
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +13 -13
- package/docs/api/interfaces/OrganisationContextType.md +21 -21
- package/docs/api/interfaces/OrganisationMembership.md +15 -15
- package/docs/api/interfaces/OrganisationProviderProps.md +59 -2
- package/docs/api/interfaces/OrganisationSecurityError.md +5 -5
- package/docs/api/interfaces/PaceAppLayoutProps.md +26 -39
- 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/ProgressProps.md +50 -0
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
- package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
- package/docs/api/interfaces/PublicPageLayoutProps.md +15 -15
- package/docs/api/interfaces/RBACAccessValidateParams.md +52 -0
- package/docs/api/interfaces/RBACAccessValidateResult.md +41 -0
- package/docs/api/interfaces/RBACAuditLogParams.md +85 -0
- package/docs/api/interfaces/RBACAuditLogResult.md +52 -0
- package/docs/api/interfaces/RBACConfig.md +2 -2
- package/docs/api/interfaces/RBACContext.md +52 -0
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +74 -0
- package/docs/api/interfaces/RBACPermissionCheckParams.md +74 -0
- package/docs/api/interfaces/RBACPermissionCheckResult.md +52 -0
- package/docs/api/interfaces/RBACPermissionsGetParams.md +63 -0
- package/docs/api/interfaces/RBACPermissionsGetResult.md +63 -0
- package/docs/api/interfaces/RBACResult.md +58 -0
- package/docs/api/interfaces/RBACRoleGrantParams.md +63 -0
- package/docs/api/interfaces/RBACRoleGrantResult.md +52 -0
- package/docs/api/interfaces/RBACRoleRevokeParams.md +63 -0
- package/docs/api/interfaces/RBACRoleRevokeResult.md +52 -0
- package/docs/api/interfaces/RBACRoleValidateParams.md +52 -0
- package/docs/api/interfaces/RBACRoleValidateResult.md +63 -0
- package/docs/api/interfaces/RBACRolesListParams.md +52 -0
- package/docs/api/interfaces/RBACRolesListResult.md +74 -0
- package/docs/api/interfaces/RBACSessionTrackParams.md +74 -0
- package/docs/api/interfaces/RBACSessionTrackResult.md +52 -0
- 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 +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/SessionRestorationLoaderProps.md +15 -2
- 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 +43 -2
- package/docs/api/interfaces/TextareaProps.md +2 -2
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +61 -61
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
- 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 +4 -4
- package/docs/api/interfaces/UserProfile.md +7 -7
- package/docs/api/modules.md +484 -462
- package/docs/api-reference/components.md +186 -15
- package/docs/api-reference/deprecated.md +376 -0
- package/docs/api-reference/hooks.md +149 -19
- package/docs/api-reference/providers.md +61 -6
- package/docs/api-reference/rpc-functions.md +397 -0
- package/docs/api-reference/types.md +135 -78
- package/docs/api-reference/utilities.md +51 -380
- package/docs/architecture/README.md +49 -3
- package/docs/architecture/database-schema-requirements.md +40 -3
- package/docs/architecture/rbac-security-architecture.md +41 -4
- package/docs/architecture/services.md +127 -42
- package/docs/best-practices/README.md +51 -5
- package/docs/best-practices/accessibility.md +32 -3
- package/docs/best-practices/common-patterns.md +50 -3
- package/docs/best-practices/deployment.md +50 -4
- package/docs/best-practices/performance.md +50 -3
- package/docs/best-practices/security.md +94 -41
- package/docs/best-practices/testing.md +33 -4
- package/docs/core-concepts/authentication.md +5 -5
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +3 -3
- package/docs/core-concepts/permissions.md +3 -3
- package/docs/core-concepts/rbac-system.md +5 -5
- package/docs/documentation-index.md +30 -8
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +7 -5
- package/docs/getting-started/examples/basic-auth-app.md +3 -0
- package/docs/getting-started/examples/full-featured-app.md +5 -3
- package/docs/getting-started/faq.md +6 -6
- package/docs/getting-started/installation-guide.md +192 -13
- package/docs/getting-started/local-development.md +303 -0
- package/docs/getting-started/quick-reference.md +3 -3
- package/docs/getting-started/quick-start.md +517 -0
- package/docs/implementation-guides/app-layout.md +45 -3
- package/docs/implementation-guides/authentication.md +66 -7
- package/docs/implementation-guides/component-styling.md +53 -3
- package/docs/implementation-guides/data-tables.md +76 -7
- package/docs/implementation-guides/datatable-filtering.md +1 -2
- package/docs/implementation-guides/datatable-rbac-usage.md +0 -1
- package/docs/implementation-guides/dynamic-colors.md +155 -4
- package/docs/implementation-guides/file-reference-system.md +72 -3
- package/docs/implementation-guides/file-upload-storage.md +72 -3
- package/docs/implementation-guides/forms.md +53 -3
- package/docs/implementation-guides/inactivity-tracking.md +53 -3
- package/docs/implementation-guides/large-datasets.md +1 -1
- package/docs/implementation-guides/navigation.md +55 -5
- package/docs/implementation-guides/organisation-security.md +72 -3
- package/docs/implementation-guides/performance.md +57 -1
- package/docs/implementation-guides/permission-enforcement.md +81 -8
- package/docs/implementation-guides/public-pages.md +560 -14
- package/docs/migration/MIGRATION_GUIDE.md +409 -50
- package/docs/migration/README.md +37 -3
- package/docs/migration/organisation-context-timing-fix.md +39 -4
- package/docs/migration/quick-migration-guide.md +41 -5
- package/docs/migration/rbac-migration.md +59 -3
- package/docs/migration/service-architecture.md +77 -14
- package/docs/rbac/README.md +79 -3
- package/docs/rbac/advanced-patterns.md +47 -3
- package/docs/rbac/api-reference.md +77 -8
- package/docs/rbac/event-based-apps.md +50 -5
- package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
- package/docs/rbac/examples.md +39 -3
- package/docs/rbac/getting-started.md +63 -4
- package/docs/rbac/quick-start.md +57 -5
- package/docs/rbac/rbac-rls-integration.md +68 -6
- package/docs/rbac/super-admin-guide.md +47 -3
- package/docs/rbac/troubleshooting.md +3 -3
- package/docs/security/README.md +68 -3
- package/docs/security/checklist.md +50 -3
- package/docs/standards/01-architecture-standard.md +39 -0
- package/docs/standards/02-api-and-rpc-standard.md +39 -0
- package/docs/standards/03-component-standard.md +32 -0
- package/docs/standards/04-code-style-standard.md +32 -0
- package/docs/standards/05-security-standard.md +30 -0
- package/docs/standards/06-testing-and-docs-standard.md +29 -0
- package/docs/standards/README.md +35 -0
- package/docs/styles/README.md +89 -8
- package/docs/testing/README.md +175 -24
- package/docs/troubleshooting/README.md +50 -3
- package/docs/troubleshooting/common-issues.md +271 -5
- package/docs/troubleshooting/debugging.md +54 -1
- package/docs/troubleshooting/migration.md +54 -1
- package/docs/troubleshooting/organisation-context-setup.md +29 -3
- package/docs/troubleshooting/styling-issues.md +246 -4
- package/{src/components/DataTable/examples → examples/DataTable}/GroupingAggregationExample.tsx +1 -1
- package/examples/{components 2/DataTable/HierarchicalActionsExample.tsx → DataTable/HierarchicalActionsExample.tsx} +7 -6
- package/examples/{components 2/DataTable/HierarchicalExample.tsx → DataTable/HierarchicalExample.tsx} +8 -6
- package/examples/{components 2/DataTable/PerformanceExample.tsx → DataTable/PerformanceExample.tsx} +2 -2
- package/examples/{components 2/DataTable/index.ts → DataTable/index.ts} +1 -0
- package/{src/components/Dialog/examples → examples/Dialog}/HtmlDialogExample.tsx +3 -3
- package/examples/{components 2/Dialog/ScrollableDialogExample.tsx → Dialog/ScrollableDialogExample.tsx} +1 -1
- package/{src/components/Dialog/examples → examples/Dialog}/SmartDialogExample.tsx +1 -1
- package/examples/{components 2/Dialog/index.ts → Dialog/index.ts} +0 -3
- package/examples/{features/public-pages → PublicPages}/CorrectPublicPageImplementation.tsx +52 -17
- package/examples/{features/public-pages → PublicPages}/PublicEventPage.tsx +65 -35
- package/examples/{features/public-pages → PublicPages}/PublicPageApp.tsx +52 -18
- package/examples/{features/public-pages → PublicPages}/PublicPageUsageExample.tsx +28 -15
- package/examples/README.md +81 -33
- package/examples/index.ts +14 -12
- package/examples/{RBAC → rbac}/CompleteRBACExample.tsx +1 -1
- package/examples/{features/rbac → rbac}/EventBasedApp.tsx +4 -4
- package/examples/{features/rbac → rbac}/PermissionExample.tsx +5 -3
- package/package.json +21 -27
- package/src/__tests__/helpers/test-utils.tsx +29 -3
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +7 -5
- package/src/components/Alert/Alert.test.tsx +2 -2
- package/src/components/Alert/Alert.tsx +4 -4
- package/src/components/Avatar/Avatar.test.tsx +17 -6
- package/src/components/Badge/Badge.test.tsx +1 -1
- package/src/components/Badge/Badge.tsx +2 -2
- package/src/components/Button/Button.test.tsx +2 -2
- package/src/components/Button/Button.tsx +11 -7
- package/src/components/Calendar/Calendar.test.tsx +41 -8
- package/src/components/Calendar/Calendar.tsx +39 -36
- package/src/components/Card/Card.tsx +51 -13
- package/src/components/Checkbox/Checkbox.test.tsx +36 -12
- package/src/components/DataTable/DataTable.test.tsx +1 -1
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +13 -7
- package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +14 -42
- package/src/components/DataTable/__tests__/DataTable.export.test.tsx +13 -10
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +14 -11
- package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +4 -2
- package/src/components/DataTable/__tests__/DataTable.test.tsx +13 -7
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +13 -10
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +15 -11
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +12 -6
- package/src/components/DataTable/__tests__/keyboard.test.tsx +12 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +10 -6
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +1 -1
- package/src/components/DataTable/components/DataTableBody.tsx +10 -25
- package/src/components/DataTable/components/DataTableCore.tsx +1 -1
- package/src/components/DataTable/components/FilterRow.tsx +3 -1
- package/src/components/DataTable/components/ImportModal.tsx +1 -1
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +9 -9
- package/src/components/DataTable/core/ColumnFactory.ts +6 -6
- package/src/components/DataTable/core/DataTableContext.tsx +14 -10
- package/src/components/DataTable/core/LocalDataAdapter.ts +2 -1
- package/src/components/DataTable/core/PluginRegistry.ts +3 -3
- package/src/components/DataTable/core/StateManager.ts +12 -11
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +104 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +101 -0
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +84 -0
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +102 -0
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +104 -0
- package/src/components/DataTable/core/interfaces.ts +17 -17
- package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +124 -0
- package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +117 -0
- package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +102 -0
- package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +53 -0
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +0 -2
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +9 -8
- package/src/components/DataTable/types.ts +5 -5
- package/src/components/DataTable/utils/aggregationUtils.ts +4 -4
- package/src/components/DataTable/utils/columnUtils.ts +3 -2
- package/src/components/DataTable/utils/debugTools.ts +1 -1
- package/src/components/DataTable/utils/exportUtils.ts +6 -6
- package/src/components/DataTable/utils/hierarchicalSorting.ts +6 -6
- package/src/components/DataTable/utils/hierarchicalUtils.ts +0 -8
- package/src/components/DataTable/utils/index.ts +0 -1
- package/src/components/DataTable/utils/performanceUtils.ts +9 -4
- package/src/components/Dialog/Dialog.test.tsx +49 -27
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +13 -8
- package/src/components/EventSelector/EventSelector.test.tsx +60 -12
- package/src/components/EventSelector/EventSelector.tsx +38 -15
- package/src/components/EventSelector/index.ts +2 -2
- package/src/components/FileDisplay/FileDisplay.test.tsx +143 -85
- package/src/components/FileDisplay/FileDisplay.tsx +1 -0
- package/src/components/FileUpload/FileUpload.test.tsx +532 -152
- package/src/components/FileUpload/FileUpload.tsx +43 -8
- package/src/components/Footer/Footer.test.tsx +19 -14
- package/src/components/Form/Form.test.tsx +96 -14
- package/src/components/Form/Form.tsx +210 -1
- package/src/components/Form/index.ts +3 -7
- package/src/components/Header/Header.test.tsx +24 -17
- package/src/components/Header/Header.tsx +3 -1
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -4
- package/src/components/Input/Input.test.tsx +61 -36
- package/src/components/Label/{__tests__/Label.test.tsx → Label.test.tsx} +2 -2
- package/src/components/Label/Label.tsx +2 -3
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +6 -5
- package/src/components/LoadingSpinner/LoadingSpinner.tsx +6 -2
- package/src/components/LoginForm/LoginForm.test.tsx +14 -13
- package/src/components/LoginForm/LoginForm.tsx +1 -1
- package/src/components/LoginForm/index.ts +7 -0
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +233 -20
- package/src/components/NavigationMenu/NavigationMenu.tsx +191 -55
- package/src/components/NavigationMenu/index.ts +1 -1
- package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +20 -11
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +1 -1
- package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.integration.test.tsx → PaceAppLayout.integration.test.tsx} +272 -79
- package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.performance.test.tsx → PaceAppLayout.performance.test.tsx} +155 -32
- package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.security.test.tsx → PaceAppLayout.security.test.tsx} +211 -65
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +498 -210
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +63 -64
- package/src/components/PaceAppLayout/test-setup.tsx +192 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +193 -39
- package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.test.tsx +2 -2
- package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.tsx +10 -4
- package/src/components/PasswordChange/index.ts +2 -0
- package/src/components/Progress/Progress.test.tsx +11 -0
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/Progress/index.ts +10 -0
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +2 -1
- package/src/components/PublicLayout/PublicLayout.test.tsx +1210 -0
- package/src/components/PublicLayout/PublicPageLayout.tsx +190 -36
- package/src/components/PublicLayout/PublicPageProvider.tsx +8 -7
- package/src/components/PublicLayout/index.ts +10 -28
- package/src/components/Select/Select.test.tsx +7 -7
- package/src/components/Select/Select.tsx +277 -11
- package/src/components/Select/index.ts +1 -2
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +232 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +40 -19
- package/src/components/Table/{__tests__/Table.test.tsx → Table.test.tsx} +94 -41
- package/src/components/Tabs/Tabs.test.tsx +10 -9
- package/src/components/Tabs/Tabs.tsx +61 -33
- package/src/components/Textarea/Textarea.test.tsx +31 -18
- package/src/components/Toast/Toast.tsx +2 -2
- package/src/components/Tooltip/Tooltip.test.tsx +1 -1
- package/src/components/UserMenu/UserMenu.test.tsx +7 -6
- package/src/components/UserMenu/UserMenu.tsx +2 -2
- package/src/components/index.ts +5 -4
- package/src/constants/performance.ts +19 -8
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +21 -22
- package/src/hooks/__tests__/useEvents.unit.test.ts +5 -4
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +2 -2
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -0
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +16 -11
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +1 -3
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +1 -3
- package/src/hooks/__tests__/useRBAC.unit.test.ts +24 -2
- package/src/hooks/index.ts +4 -0
- package/src/hooks/public/index.ts +2 -0
- package/src/hooks/public/usePublicEvent.ts +4 -6
- package/src/hooks/public/usePublicRouteParams.ts +1 -1
- package/src/hooks/services/useAuth.ts +2 -4
- package/src/hooks/services/useCurrentEvent.ts +1 -1
- package/src/hooks/useAppConfig.ts +1 -1
- package/src/hooks/useDataTablePerformance.ts +2 -2
- package/src/hooks/useEventTheme.ts +1 -1
- package/src/hooks/useEvents.ts +51 -10
- package/src/hooks/useOrganisationPermissions.test.ts +3 -3
- package/src/hooks/useOrganisationPermissions.ts +1 -1
- package/src/hooks/useOrganisationSecurity.ts +2 -2
- package/src/hooks/usePermissionCache.test.ts +9 -9
- package/src/hooks/usePermissionCache.ts +2 -2
- package/src/index.ts +19 -12
- package/src/providers/OrganisationProvider.tsx +73 -9
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +113 -13
- package/src/providers/__tests__/AuthProvider.test.tsx +2 -1
- package/src/providers/__tests__/EventProvider.test.tsx +24 -15
- package/src/providers/__tests__/OrganisationProvider.test.tsx +87 -36
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +80 -24
- package/src/providers/index.ts +0 -3
- package/src/providers/services/AuthServiceProvider.tsx +2 -17
- package/src/providers/services/EventServiceProvider.tsx +11 -16
- package/src/providers/services/InactivityServiceProvider.tsx +9 -12
- package/src/providers/services/OrganisationServiceProvider.tsx +9 -12
- package/src/providers/services/UnifiedAuthProvider.tsx +85 -18
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +11 -4
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +105 -21
- package/src/rbac/adapters.tsx +1 -1
- package/src/rbac/api.ts +20 -4
- package/src/rbac/audit-enhanced.ts +47 -2
- package/src/rbac/audit.ts +47 -2
- package/src/rbac/components/NavigationGuard.tsx +1 -1
- package/src/rbac/components/NavigationProvider.test.tsx +7 -6
- package/src/rbac/components/NavigationProvider.tsx +1 -1
- package/src/rbac/components/PagePermissionGuard.tsx +1 -1
- package/src/rbac/components/PagePermissionProvider.test.tsx +7 -6
- package/src/rbac/components/PagePermissionProvider.tsx +1 -1
- package/src/rbac/components/PermissionEnforcer.tsx +1 -1
- package/src/rbac/components/RoleBasedRouter.tsx +1 -1
- package/src/rbac/components/SecureDataProvider.test.tsx +7 -6
- package/src/rbac/components/SecureDataProvider.tsx +1 -1
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +6 -6
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +11 -10
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +10 -11
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +19 -15
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +13 -12
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +19 -15
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +18 -18
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +11 -10
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +8 -7
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +10 -11
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +48 -19
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +476 -0
- package/src/rbac/hooks/index.ts +3 -0
- package/src/rbac/hooks/usePermissions.ts +31 -85
- package/src/rbac/hooks/useRBAC.test.ts +13 -1
- package/src/rbac/hooks/useRBAC.ts +13 -67
- package/src/rbac/hooks/useResolvedScope.ts +11 -0
- package/src/rbac/hooks/useSecureSupabase.ts +308 -0
- package/src/rbac/index.ts +3 -0
- package/src/rbac/secureClient.ts +53 -6
- package/src/rbac/security.ts +37 -1
- package/src/{types/rbac-functions.ts → rbac/types/functions.ts} +30 -30
- package/src/rbac/types.ts +3 -2
- package/src/services/AuthService.ts +33 -25
- package/src/services/EventService.ts +57 -31
- package/src/services/InactivityService.ts +33 -53
- package/src/services/OrganisationService.ts +36 -40
- package/src/services/__tests__/AuthService.restoreSession.test.ts +6 -2
- package/src/services/__tests__/EventService.test.ts +67 -33
- package/src/services/interfaces/IEventService.ts +1 -1
- package/src/styles/core.css +2 -2
- package/src/styles/index.ts +1 -5
- package/src/types/__tests__/guards.test.ts +1 -1
- package/src/types/__tests__/type-validation.test.ts +0 -1
- package/src/types/auth.ts +42 -2
- package/src/types/core.ts +251 -0
- package/src/types/database.ts +11 -496
- package/src/types/event.ts +102 -0
- package/src/types/file-reference.ts +6 -4
- package/src/types/guards.ts +2 -1
- package/src/types/index.ts +48 -14
- package/src/types/lodash.debounce.d.ts +15 -0
- package/src/types/organisation.ts +14 -10
- package/src/types/supabase.ts +15 -17
- package/src/utils/__tests__/secureErrors.unit.test.ts +1 -1
- package/src/utils/__tests__/validationUtils.unit.test.ts +0 -29
- package/src/utils/app/appNameResolver.ts +1 -1
- package/src/utils/dynamic/dynamicUtils.ts +3 -2
- package/src/utils/file-reference/index.ts +25 -6
- package/src/utils/security/secureErrors.ts +1 -1
- package/src/utils/validation/index.ts +6 -12
- package/src/utils/validation/validationUtils.ts +0 -13
- package/dist/UnifiedAuthProvider-BMJAP6Z7.js +0 -16
- package/dist/auth-DReDSLq9.d.ts +0 -16
- package/dist/chunk-56XJ3TU6.js +0 -11
- package/dist/chunk-56XJ3TU6.js.map +0 -1
- package/dist/chunk-6HLVGAZG.js.map +0 -1
- package/dist/chunk-7QCC6MCP.js +0 -288
- package/dist/chunk-BESYRHQM.js.map +0 -1
- package/dist/chunk-BJPBT3CU.js +0 -21
- package/dist/chunk-BJPBT3CU.js.map +0 -1
- package/dist/chunk-BVYWGZVV.js.map +0 -1
- package/dist/chunk-CPTUD43C.js.map +0 -1
- package/dist/chunk-CX5M4ZAG.js.map +0 -1
- package/dist/chunk-ERGKJX4D.js +0 -15
- package/dist/chunk-ERGKJX4D.js.map +0 -1
- package/dist/chunk-ERISIBYU.js.map +0 -1
- package/dist/chunk-GQA2LIAE.js.map +0 -1
- package/dist/chunk-JISYG63F.js +0 -70
- package/dist/chunk-JISYG63F.js.map +0 -1
- package/dist/chunk-MSHEVJXS.js +0 -27
- package/dist/chunk-MSHEVJXS.js.map +0 -1
- package/dist/chunk-N5YCCUG5.js.map +0 -1
- package/dist/chunk-ONI7Y733.js.map +0 -1
- package/dist/chunk-OWAG3GSU.js.map +0 -1
- package/dist/chunk-P6UUHOIF.js.map +0 -1
- package/dist/chunk-PKW27QVS.js +0 -61
- package/dist/chunk-PKW27QVS.js.map +0 -1
- package/dist/chunk-Q5QRDWKI.js.map +0 -1
- package/dist/chunk-S5OFRT4M.js.map +0 -1
- package/dist/chunk-SBVILCCA.js.map +0 -1
- package/dist/chunk-WM26XK7I.js +0 -2432
- package/dist/chunk-WM26XK7I.js.map +0 -1
- package/dist/chunk-XDNLUEXI.js +0 -138
- package/dist/chunk-XJ2HZOBU.js.map +0 -1
- package/dist/chunk-ZZ2SS7NI.js +0 -237
- package/dist/chunk-ZZ2SS7NI.js.map +0 -1
- package/dist/database-C6jy7EOu.d.ts +0 -500
- package/dist/organisation-D6qRDtbF.d.ts +0 -93
- package/dist/schema-DTDZQe2u.d.ts +0 -28
- package/dist/unified-DQ4VcT7H.d.ts +0 -198
- package/dist/useInactivityTracker-TO6ZOF35.js +0 -11
- package/dist/validation.d.ts +0 -47
- package/dist/validation.js +0 -24
- package/dist/validation.js.map +0 -1
- package/docs/DOCUMENTATION_AUDIT.md +0 -172
- package/docs/DOCUMENTATION_STANDARD.md +0 -137
- package/docs/api/classes/PublicErrorBoundary.md +0 -132
- package/docs/api/interfaces/EventLogoProps.md +0 -152
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +0 -94
- package/docs/api/interfaces/PublicErrorBoundaryState.md +0 -68
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +0 -86
- package/docs/architecture/rpc-function-standards.md +0 -1106
- package/docs/getting-started/consuming-app-vite-config.md +0 -239
- package/docs/implementation-guides/event-theming-summary.md +0 -226
- package/docs/implementation-guides/public-pages-advanced.md +0 -1038
- package/docs/migration/v0.4.15-tailwind-scanning.md +0 -278
- package/docs/migration/v0.4.16-css-first-approach.md +0 -312
- package/docs/migration/v0.4.17-source-path-fix.md +0 -235
- package/docs/rbac/RBAC_EVENT_CONTEXT_LOADING.md +0 -222
- package/docs/rbac/RBAC_LOGIN_SAFETY_FIX.md +0 -95
- package/docs/rbac/RBAC_V0.5.147_FIX.md +0 -117
- package/docs/rbac/README-rbac-rls-integration.md +0 -374
- package/docs/styles/usage.md +0 -227
- package/docs/testing/visual-testing.md +0 -120
- package/docs/troubleshooting/DEBUG_NETWORK_ERROR.md +0 -152
- package/docs/troubleshooting/FIX_SUPABASE_CORS.md +0 -184
- package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +0 -193
- package/docs/troubleshooting/database-view-compatibility.md +0 -125
- package/docs/troubleshooting/react-hooks-issue-analysis.md +0 -172
- package/docs/troubleshooting/tailwind-content-scanning.md +0 -219
- package/examples/RBAC/EventBasedApp.tsx +0 -239
- package/examples/RBAC/PermissionExample.tsx +0 -151
- package/examples/STRUCTURE.md +0 -125
- package/examples/components 2/Dialog/BasicHtmlTest.tsx +0 -55
- package/examples/components 2/Dialog/DebugHtmlExample.tsx +0 -68
- package/examples/components 2/Dialog/HtmlDialogExample.tsx +0 -202
- package/examples/components 2/Dialog/SimpleHtmlTest.tsx +0 -61
- package/examples/components 2/Dialog/SmartDialogExample.tsx +0 -322
- package/examples/components 2/index.ts +0 -11
- package/examples/features/index.ts +0 -12
- package/examples/features/rbac/CompleteRBACExample.tsx +0 -324
- package/examples/features/rbac/index.ts +0 -13
- package/examples/public-pages/CorrectPublicPageImplementation.tsx +0 -301
- package/examples/public-pages/PublicEventPage.tsx +0 -274
- package/examples/public-pages/PublicPageApp.tsx +0 -308
- package/examples/public-pages/PublicPageUsageExample.tsx +0 -216
- package/examples/public-pages/index.ts +0 -14
- package/src/__tests__/TEST_STANDARD.md +0 -1008
- package/src/components/Checkbox/__mocks__/Checkbox.tsx +0 -2
- package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +0 -421
- package/src/components/DataTable/examples/HierarchicalExample.tsx +0 -475
- package/src/components/DataTable/examples/InitialPageSizeExample.tsx +0 -177
- package/src/components/DataTable/examples/PerformanceExample.tsx +0 -506
- package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +0 -316
- package/src/components/DataTable/examples/__tests__/HierarchicalExample.test.tsx +0 -45
- package/src/components/DataTable/examples/__tests__/InitialPageSizeExample.test.tsx +0 -211
- package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +0 -126
- package/src/components/Dialog/README.md +0 -804
- package/src/components/Dialog/examples/BasicHtmlTest.tsx +0 -55
- package/src/components/Dialog/examples/DebugHtmlExample.tsx +0 -68
- package/src/components/Dialog/examples/ScrollableDialogExample.tsx +0 -290
- package/src/components/Dialog/examples/SimpleHtmlTest.tsx +0 -61
- package/src/components/Dialog/examples/__tests__/HtmlDialogExample.test.tsx +0 -71
- package/src/components/Dialog/examples/__tests__/SimpleHtmlTest.test.tsx +0 -122
- package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +0 -147
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +0 -611
- package/src/components/Dialog/utils/safeHtml.ts +0 -185
- package/src/components/EventSelector/types.ts +0 -79
- package/src/components/Form/FormErrorSummary.tsx +0 -113
- package/src/components/Form/FormField.tsx +0 -249
- package/src/components/Form/FormFieldset.tsx +0 -127
- package/src/components/Form/FormLiveRegion.tsx +0 -198
- package/src/components/Input/__mocks__/Input.tsx +0 -2
- package/src/components/NavigationMenu/types.ts +0 -85
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +0 -326
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -1078
- package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
- package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
- package/src/components/PasswordReset/index.ts +0 -2
- package/src/components/ProtectedRoute/README.md +0 -164
- package/src/components/PublicLayout/EventLogo.tsx +0 -175
- package/src/components/PublicLayout/PublicErrorBoundary.tsx +0 -282
- package/src/components/PublicLayout/PublicLoadingSpinner.tsx +0 -216
- package/src/components/PublicLayout/PublicPageContextChecker.tsx +0 -131
- package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
- package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
- package/src/components/PublicLayout/PublicPageFooter.tsx +0 -124
- package/src/components/PublicLayout/PublicPageHeader.tsx +0 -209
- package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +0 -449
- package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +0 -393
- package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +0 -192
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +0 -351
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +0 -402
- package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +0 -460
- package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +0 -313
- package/src/components/Select/hooks.ts +0 -289
- package/src/hooks/useCounter.test.ts +0 -131
- package/src/hooks/useDebounce.test.ts +0 -375
- package/src/providers/AuthProvider.tsx +0 -15
- package/src/providers/EventProvider.tsx +0 -16
- package/src/providers/InactivityProvider.tsx +0 -15
- package/src/providers/OrganisationProvider.context.test.tsx +0 -169
- package/src/providers/UnifiedAuthProvider.tsx +0 -15
- package/src/types/theme.ts +0 -6
- package/src/types/unified.ts +0 -265
- package/src/utils/appConfig.ts +0 -47
- package/src/utils/appIdResolver.test.ts +0 -499
- package/src/utils/appIdResolver.ts +0 -130
- package/src/utils/appNameResolver.simple.test.ts +0 -212
- package/src/utils/appNameResolver.test.ts +0 -121
- package/src/utils/appNameResolver.ts +0 -191
- package/src/utils/audit.ts +0 -127
- package/src/utils/auth-utils.ts +0 -96
- package/src/utils/bundleAnalysis.ts +0 -129
- package/src/utils/debugLogger.ts +0 -67
- package/src/utils/deviceFingerprint.ts +0 -215
- package/src/utils/dynamicUtils.ts +0 -105
- package/src/utils/file-reference.test.ts +0 -788
- package/src/utils/file-reference.ts +0 -519
- package/src/utils/formatDate.test.ts +0 -237
- package/src/utils/formatting.ts +0 -170
- package/src/utils/lazyLoad.tsx +0 -44
- package/src/utils/logger.ts +0 -179
- package/src/utils/organisationContext.test.ts +0 -322
- package/src/utils/organisationContext.ts +0 -153
- package/src/utils/performanceBenchmark.ts +0 -64
- package/src/utils/performanceBudgets.ts +0 -110
- package/src/utils/permissionTypes.ts +0 -37
- package/src/utils/permissionUtils.test.ts +0 -393
- package/src/utils/permissionUtils.ts +0 -34
- package/src/utils/sanitization.ts +0 -264
- package/src/utils/schemaUtils.ts +0 -37
- package/src/utils/secureDataAccess.test.ts +0 -711
- package/src/utils/secureDataAccess.ts +0 -377
- package/src/utils/secureErrors.ts +0 -79
- package/src/utils/security.ts +0 -156
- package/src/utils/securityMonitor.ts +0 -45
- package/src/utils/sessionTracking.ts +0 -126
- package/src/utils/validation.ts +0 -111
- package/src/utils/validationUtils.ts +0 -120
- package/src/validation/index.ts +0 -12
- /package/dist/{DataTable-4VSEJQ7D.js.map → DataTable-QAB34V6K.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-BMJAP6Z7.js.map → UnifiedAuthProvider-7F6T4B6K.js.map} +0 -0
- /package/dist/{api-45XYYO2A.js.map → api-ROMBCNKU.js.map} +0 -0
- /package/dist/{audit-64X3VJXB.js.map → audit-WRS3KJKI.js.map} +0 -0
- /package/dist/{chunk-PLDDJCW6.js.map → chunk-7D4SUZUM.js.map} +0 -0
- /package/dist/{useInactivityTracker-TO6ZOF35.js.map → chunk-KQCRWDSA.js.map} +0 -0
- /package/examples/{components 2/DataTable → DataTable}/InitialPageSizeExample.tsx +0 -0
- /package/examples/{features/public-pages → PublicPages}/index.ts +0 -0
- /package/examples/{RBAC → rbac}/index.ts +0 -0
|
@@ -1,1008 +0,0 @@
|
|
|
1
|
-
# Testing Standard
|
|
2
|
-
|
|
3
|
-
The authoritative guide for writing world-class tests in the pace-core project. Every test contribution should follow these standards to ensure reliability, maintainability, and comprehensive coverage.
|
|
4
|
-
|
|
5
|
-
## 🎯 Testing Philosophy
|
|
6
|
-
|
|
7
|
-
### Core Principles
|
|
8
|
-
|
|
9
|
-
1. **Test Behavior, Not Implementation** - Focus on what users see and do, not internal code structure
|
|
10
|
-
2. **Fast & Reliable** - Tests should run quickly and produce consistent results
|
|
11
|
-
3. **Independent & Isolated** - Tests should not depend on each other or external state
|
|
12
|
-
4. **Self-Documenting** - Tests should clearly express intent and expected behavior
|
|
13
|
-
5. **Maintainable** - Tests should be easy to update when requirements change
|
|
14
|
-
|
|
15
|
-
### The Testing Pyramid
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
/\
|
|
19
|
-
/ \ E2E Tests (Few)
|
|
20
|
-
/____\
|
|
21
|
-
/ \ Integration Tests (Some)
|
|
22
|
-
/________\
|
|
23
|
-
Unit Tests (Many)
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
**Distribution Guidelines:**
|
|
27
|
-
- **Unit Tests (80%)**: Fast, isolated tests for individual functions/components
|
|
28
|
-
- **Integration Tests (15%)**: Test component interactions and data flow
|
|
29
|
-
- **E2E Tests (5%)**: Full user journey validation
|
|
30
|
-
|
|
31
|
-
## 🏗️ Test Organization
|
|
32
|
-
|
|
33
|
-
### File Structure
|
|
34
|
-
|
|
35
|
-
**✅ Preferred: Colocated Tests**
|
|
36
|
-
```
|
|
37
|
-
src/
|
|
38
|
-
├── components/
|
|
39
|
-
│ ├── Button/
|
|
40
|
-
│ │ ├── Button.tsx
|
|
41
|
-
│ │ └── Button.test.tsx ✅ Next to source
|
|
42
|
-
│ └── DataTable/
|
|
43
|
-
│ ├── DataTable.tsx
|
|
44
|
-
│ ├── DataTable.test.tsx ✅ Main component tests
|
|
45
|
-
│ └── __tests__/ ✅ For multiple test files
|
|
46
|
-
│ └── DataTable.integration.test.tsx
|
|
47
|
-
├── hooks/
|
|
48
|
-
│ ├── useCounter.ts
|
|
49
|
-
│ └── useCounter.test.ts ✅ Colocated
|
|
50
|
-
└── services/
|
|
51
|
-
├── AuthService.ts
|
|
52
|
-
└── AuthService.test.ts ✅ Colocated
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
**When to Use `__tests__/` Directory:**
|
|
56
|
-
- Multiple test files for one source file (unit + integration)
|
|
57
|
-
- Shared test utilities within a module
|
|
58
|
-
- Integration tests spanning multiple components
|
|
59
|
-
|
|
60
|
-
**Central `src/__tests__/` Directory - ONLY for:**
|
|
61
|
-
- Cross-module integration tests
|
|
62
|
-
- Shared test utilities and fixtures
|
|
63
|
-
- Test configuration files
|
|
64
|
-
|
|
65
|
-
### File Naming Conventions
|
|
66
|
-
|
|
67
|
-
- `ComponentName.test.tsx` - Component tests
|
|
68
|
-
- `hookName.test.ts` - Hook tests
|
|
69
|
-
- `serviceName.test.ts` - Service tests
|
|
70
|
-
- `feature.integration.test.tsx` - Integration tests
|
|
71
|
-
- `utils.unit.test.ts` - Utility function tests
|
|
72
|
-
|
|
73
|
-
## 📝 Test Structure & Naming
|
|
74
|
-
|
|
75
|
-
### Describe Block Organization
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
describe('ComponentName', () => {
|
|
79
|
-
describe('Rendering', () => {
|
|
80
|
-
it('renders with default props', () => {});
|
|
81
|
-
it('renders with custom content', () => {});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
describe('User Interactions', () => {
|
|
85
|
-
it('handles click events', () => {});
|
|
86
|
-
it('handles keyboard navigation', () => {});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
describe('State Management', () => {
|
|
90
|
-
it('updates state on user input', () => {});
|
|
91
|
-
it('resets state on form submission', () => {});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
describe('Error Handling', () => {
|
|
95
|
-
it('displays error message on validation failure', () => {});
|
|
96
|
-
it('recovers from network errors', () => {});
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Test Naming Best Practices
|
|
102
|
-
|
|
103
|
-
```typescript
|
|
104
|
-
// ✅ Good - Descriptive and behavior-focused
|
|
105
|
-
it('renders submit button when form is valid', () => {});
|
|
106
|
-
it('disables submit button when required fields are empty', () => {});
|
|
107
|
-
it('shows loading spinner during form submission', () => {});
|
|
108
|
-
|
|
109
|
-
// ❌ Bad - Vague or implementation-focused
|
|
110
|
-
it('works correctly', () => {});
|
|
111
|
-
it('test button component', () => {});
|
|
112
|
-
it('should call onClick prop', () => {});
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## 🧪 Testing Patterns
|
|
116
|
-
|
|
117
|
-
### 1. Component Testing (AAA Pattern)
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
describe('Button Component', () => {
|
|
121
|
-
it('handles click events with custom handler', async () => {
|
|
122
|
-
// Arrange
|
|
123
|
-
const handleClick = vi.fn();
|
|
124
|
-
const user = userEvent.setup();
|
|
125
|
-
|
|
126
|
-
render(<Button onClick={handleClick}>Click me</Button>);
|
|
127
|
-
|
|
128
|
-
// Act
|
|
129
|
-
await user.click(screen.getByRole('button', { name: 'Click me' }));
|
|
130
|
-
|
|
131
|
-
// Assert
|
|
132
|
-
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### 2. Hook Testing
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
describe('useCounter Hook', () => {
|
|
141
|
-
it('initializes with provided value', () => {
|
|
142
|
-
const { result } = renderHook(() => useCounter(5));
|
|
143
|
-
|
|
144
|
-
expect(result.current.count).toBe(5);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('increments count when increment is called', () => {
|
|
148
|
-
const { result } = renderHook(() => useCounter(0));
|
|
149
|
-
|
|
150
|
-
act(() => {
|
|
151
|
-
result.current.increment();
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
expect(result.current.count).toBe(1);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### 3. Service Testing
|
|
160
|
-
|
|
161
|
-
```typescript
|
|
162
|
-
describe('AuthService', () => {
|
|
163
|
-
let mockSupabase: ReturnType<typeof createMockSupabaseClient>;
|
|
164
|
-
let authService: AuthService;
|
|
165
|
-
|
|
166
|
-
beforeEach(() => {
|
|
167
|
-
mockSupabase = createMockSupabaseClient();
|
|
168
|
-
authService = new AuthService(mockSupabase);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it('signs in user with valid credentials', async () => {
|
|
172
|
-
const mockUser = { id: '123', email: 'user@example.com' };
|
|
173
|
-
|
|
174
|
-
mockSupabase.auth.signInWithPassword.mockResolvedValue({
|
|
175
|
-
data: { user: mockUser, session: {} },
|
|
176
|
-
error: null
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
const result = await authService.signIn({
|
|
180
|
-
email: 'user@example.com',
|
|
181
|
-
password: 'password'
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
expect(result.user).toEqual(mockUser);
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### 4. Integration Testing
|
|
190
|
-
|
|
191
|
-
```typescript
|
|
192
|
-
describe('User Registration Flow', () => {
|
|
193
|
-
it('completes full registration workflow', async () => {
|
|
194
|
-
const user = userEvent.setup();
|
|
195
|
-
|
|
196
|
-
render(<RegistrationForm />);
|
|
197
|
-
|
|
198
|
-
// Fill form
|
|
199
|
-
await user.type(screen.getByLabelText('Email'), 'user@example.com');
|
|
200
|
-
await user.type(screen.getByLabelText('Password'), 'password123');
|
|
201
|
-
|
|
202
|
-
// Submit
|
|
203
|
-
await user.click(screen.getByRole('button', { name: 'Register' }));
|
|
204
|
-
|
|
205
|
-
// Verify success
|
|
206
|
-
expect(await screen.findByText('Registration successful')).toBeInTheDocument();
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
## 🔍 Query Best Practices
|
|
212
|
-
|
|
213
|
-
### Semantic Queries (Preferred)
|
|
214
|
-
|
|
215
|
-
```typescript
|
|
216
|
-
// ✅ Excellent - Semantic and accessible
|
|
217
|
-
screen.getByRole('button', { name: 'Submit' });
|
|
218
|
-
screen.getByLabelText('Email address');
|
|
219
|
-
screen.getByText('Welcome back');
|
|
220
|
-
screen.getByPlaceholderText('Enter your name');
|
|
221
|
-
|
|
222
|
-
// ✅ Good - Content-based
|
|
223
|
-
screen.getByDisplayValue('current-value');
|
|
224
|
-
screen.getByTitle('Close dialog');
|
|
225
|
-
|
|
226
|
-
// ⚠️ Use sparingly - When semantic queries aren't sufficient
|
|
227
|
-
screen.getByTestId('complex-widget');
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
### Query Priority Order
|
|
231
|
-
|
|
232
|
-
1. **getByRole** - Most accessible and semantic
|
|
233
|
-
2. **getByLabelText** - Form elements with labels
|
|
234
|
-
3. **getByText** - Visible text content
|
|
235
|
-
4. **getByDisplayValue** - Form elements with values
|
|
236
|
-
5. **getByAltText** - Images with alt text
|
|
237
|
-
6. **getByTitle** - Elements with title attribute
|
|
238
|
-
7. **getByTestId** - Last resort for complex cases
|
|
239
|
-
|
|
240
|
-
### Async Query Patterns
|
|
241
|
-
|
|
242
|
-
```typescript
|
|
243
|
-
// ✅ Good - Built-in waiting with findBy
|
|
244
|
-
const button = await screen.findByRole('button', { name: 'Submit' });
|
|
245
|
-
|
|
246
|
-
// ✅ Good - Wait for specific condition
|
|
247
|
-
await waitFor(() => {
|
|
248
|
-
expect(screen.getByText('Data loaded')).toBeInTheDocument();
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
// ❌ Bad - Waiting for synchronous operations
|
|
252
|
-
await waitFor(() => {
|
|
253
|
-
expect(result.current.count).toBe(0); // This is immediate!
|
|
254
|
-
});
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
## 🔧 Mocking & Test Doubles
|
|
258
|
-
|
|
259
|
-
### Mock Strategy
|
|
260
|
-
|
|
261
|
-
```typescript
|
|
262
|
-
// ✅ Good - Mock external dependencies only
|
|
263
|
-
vi.mock('../api/users', () => ({
|
|
264
|
-
fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'John' })
|
|
265
|
-
}));
|
|
266
|
-
|
|
267
|
-
// ✅ Good - Mock complex external libraries
|
|
268
|
-
vi.mock('react-router-dom', () => ({
|
|
269
|
-
useNavigate: () => vi.fn(),
|
|
270
|
-
useLocation: () => ({ pathname: '/test' })
|
|
271
|
-
}));
|
|
272
|
-
|
|
273
|
-
// ❌ Bad - Over-mocking internal utilities
|
|
274
|
-
vi.mock('../utils/formatDate'); // Usually not necessary
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
### Multi-Call Mocking
|
|
278
|
-
|
|
279
|
-
```typescript
|
|
280
|
-
// ✅ Good - Handle different calls with mockImplementation
|
|
281
|
-
mockSupabase.rpc.mockImplementation((functionName, params) => {
|
|
282
|
-
if (functionName === 'get_user') {
|
|
283
|
-
return Promise.resolve({ data: { id: '1' }, error: null });
|
|
284
|
-
}
|
|
285
|
-
if (functionName === 'get_permissions') {
|
|
286
|
-
return Promise.resolve({ data: permissions, error: null });
|
|
287
|
-
}
|
|
288
|
-
return Promise.resolve({ data: null, error: null });
|
|
289
|
-
});
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Mock Isolation Best Practices
|
|
293
|
-
|
|
294
|
-
**Problem**: Mocks can leak between test files, causing flaky tests.
|
|
295
|
-
|
|
296
|
-
**Solutions**:
|
|
297
|
-
|
|
298
|
-
```typescript
|
|
299
|
-
// ✅ Good: Use vi.hoisted() for module mocks
|
|
300
|
-
const { mockGetSignedUrl } = vi.hoisted(() => {
|
|
301
|
-
return {
|
|
302
|
-
mockGetSignedUrl: vi.fn(() => Promise.resolve({ url: 'test' }))
|
|
303
|
-
};
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
vi.mock('../utils/storage/helpers', () => ({
|
|
307
|
-
getSignedUrl: mockGetSignedUrl
|
|
308
|
-
}));
|
|
309
|
-
|
|
310
|
-
// ✅ Good: Reset mocks in beforeEach
|
|
311
|
-
beforeEach(() => {
|
|
312
|
-
mockGetSignedUrl.mockClear();
|
|
313
|
-
mockGetSignedUrl.mockReset();
|
|
314
|
-
mockGetSignedUrl.mockImplementation(() => Promise.resolve({ url: 'test' }));
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
// ✅ Good: Use vi.spyOn for better isolation (when possible)
|
|
318
|
-
const getSignedUrlSpy = vi.spyOn(storageHelpers, 'getSignedUrl');
|
|
319
|
-
getSignedUrlSpy.mockResolvedValue({ url: 'test' });
|
|
320
|
-
|
|
321
|
-
// ✅ Good: Use vi.stubGlobal for global mocks
|
|
322
|
-
vi.stubGlobal('window', undefined);
|
|
323
|
-
// Automatically restored after test
|
|
324
|
-
|
|
325
|
-
// ❌ Bad: Directly modifying global objects
|
|
326
|
-
delete global.window; // Can break other tests
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
**Mock Isolation Checklist**:
|
|
330
|
-
- [ ] Use `vi.hoisted()` for module mocks
|
|
331
|
-
- [ ] Reset mocks in `beforeEach`/`afterEach`
|
|
332
|
-
- [ ] Use `vi.stubGlobal` for global mocks
|
|
333
|
-
- [ ] Prefer `vi.spyOn` over `vi.mock` when possible
|
|
334
|
-
- [ ] Test files in isolation to verify no leakage
|
|
335
|
-
|
|
336
|
-
### Cleanup Best Practices
|
|
337
|
-
|
|
338
|
-
```typescript
|
|
339
|
-
describe('Component with Resources', () => {
|
|
340
|
-
beforeEach(() => {
|
|
341
|
-
vi.useFakeTimers();
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
afterEach(() => {
|
|
345
|
-
// Clean up timers
|
|
346
|
-
vi.clearAllTimers();
|
|
347
|
-
vi.useRealTimers();
|
|
348
|
-
|
|
349
|
-
// React Testing Library cleanup
|
|
350
|
-
cleanup();
|
|
351
|
-
|
|
352
|
-
// Clear all mocks
|
|
353
|
-
vi.clearAllMocks();
|
|
354
|
-
|
|
355
|
-
// Clear storage
|
|
356
|
-
localStorage.clear();
|
|
357
|
-
sessionStorage.clear();
|
|
358
|
-
});
|
|
359
|
-
});
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
## 🚫 Anti-Patterns to Avoid
|
|
363
|
-
|
|
364
|
-
### 1. Testing Implementation Details
|
|
365
|
-
|
|
366
|
-
```typescript
|
|
367
|
-
// ❌ Bad - Testing internal state
|
|
368
|
-
expect(component.state.isVisible).toBe(true);
|
|
369
|
-
expect(wrapper.find('.hidden-class')).toHaveLength(0);
|
|
370
|
-
|
|
371
|
-
// ✅ Good - Testing observable behavior
|
|
372
|
-
expect(screen.getByText('Visible content')).toBeInTheDocument();
|
|
373
|
-
expect(screen.queryByText('Hidden content')).not.toBeInTheDocument();
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
### 2. Skipped Tests Without Documentation
|
|
377
|
-
|
|
378
|
-
```typescript
|
|
379
|
-
// ❌ Bad - Skipped test without explanation
|
|
380
|
-
it.skip('should navigate with keyboard', () => {});
|
|
381
|
-
|
|
382
|
-
// ✅ Good - Skipped test with clear documentation
|
|
383
|
-
// TODO: Enable when keyboard navigation is implemented
|
|
384
|
-
// See: https://github.com/org/repo/issues/123
|
|
385
|
-
// Expected: Q2 2025
|
|
386
|
-
it.skip('should navigate with keyboard', () => {});
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
### 2. Brittle Selectors
|
|
390
|
-
|
|
391
|
-
```typescript
|
|
392
|
-
// ❌ Bad - Fragile and non-semantic
|
|
393
|
-
screen.getByClassName('btn-primary');
|
|
394
|
-
container.querySelector('.form > div:nth-child(2)');
|
|
395
|
-
|
|
396
|
-
// ✅ Good - Semantic and stable
|
|
397
|
-
screen.getByRole('button', { name: 'Submit' });
|
|
398
|
-
screen.getByLabelText('Email address');
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
### 3. Testing Multiple Concerns
|
|
402
|
-
|
|
403
|
-
```typescript
|
|
404
|
-
// ❌ Bad - Too many assertions in one test
|
|
405
|
-
it('renders form and validates and submits and shows success', () => {
|
|
406
|
-
// Multiple unrelated assertions
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
// ✅ Good - Single responsibility
|
|
410
|
-
it('renders form with all required fields', () => {});
|
|
411
|
-
it('validates email format on blur', () => {});
|
|
412
|
-
it('submits form with valid data', () => {});
|
|
413
|
-
it('shows success message after submission', () => {});
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
## 📊 Coverage Standards
|
|
417
|
-
|
|
418
|
-
### Coverage Thresholds
|
|
419
|
-
|
|
420
|
-
| Component Type | Target | CI Blocking | Rationale |
|
|
421
|
-
|----------------|--------|-------------|-----------|
|
|
422
|
-
| **Utils/Hooks** | 95% | Yes | Core business logic, high reuse |
|
|
423
|
-
| **UI Components** | 90% | Yes | User-facing, must be reliable |
|
|
424
|
-
| **Services** | 85% | Yes | API interactions, critical paths |
|
|
425
|
-
| **Validation** | 95% | Yes | Security and data integrity |
|
|
426
|
-
| **Overall Project** | 82% | Yes | Quality baseline |
|
|
427
|
-
|
|
428
|
-
### What to Test
|
|
429
|
-
|
|
430
|
-
- ✅ **Happy paths** - Normal user workflows
|
|
431
|
-
- ✅ **Error conditions** - Network failures, validation errors
|
|
432
|
-
- ✅ **Edge cases** - Empty states, boundary values
|
|
433
|
-
- ✅ **User interactions** - Clicks, form submissions, navigation
|
|
434
|
-
- ✅ **State changes** - Loading states, data updates
|
|
435
|
-
- ✅ **Accessibility** - Keyboard navigation, screen reader support
|
|
436
|
-
|
|
437
|
-
### What NOT to Test
|
|
438
|
-
|
|
439
|
-
- ❌ **Third-party libraries** - Already tested by maintainers
|
|
440
|
-
- ❌ **Generated code** - Auto-generated types, configs
|
|
441
|
-
- ❌ **Pure styling** - CSS classes without behavior
|
|
442
|
-
- ❌ **Type definitions** - Interfaces and type-only exports
|
|
443
|
-
|
|
444
|
-
## 🔐 RBAC Testing Patterns
|
|
445
|
-
|
|
446
|
-
### Provider Testing
|
|
447
|
-
|
|
448
|
-
```typescript
|
|
449
|
-
describe('RBACProvider', () => {
|
|
450
|
-
it('requires organisation context when configured', () => {
|
|
451
|
-
const { result } = renderHook(() => useRBAC());
|
|
452
|
-
|
|
453
|
-
expect(() => result.current.requireOrganisationContext()).toThrow(
|
|
454
|
-
'Organisation context is required'
|
|
455
|
-
);
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
it('refreshes permissions when event changes', async () => {
|
|
459
|
-
const { result } = renderHook(() => useRBAC());
|
|
460
|
-
|
|
461
|
-
act(() => {
|
|
462
|
-
result.current.setSelectedEventId('new-event-id');
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
await waitFor(() => {
|
|
466
|
-
expect(result.current.rbacLoading).toBe(false);
|
|
467
|
-
});
|
|
468
|
-
});
|
|
469
|
-
});
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
### Permission Hook Testing
|
|
473
|
-
|
|
474
|
-
```typescript
|
|
475
|
-
describe('useHasPermission', () => {
|
|
476
|
-
it('returns true when user has required permission', async () => {
|
|
477
|
-
setupRBACMock([
|
|
478
|
-
{ permission_type: 'read:users', role_name: 'viewer' }
|
|
479
|
-
]);
|
|
480
|
-
|
|
481
|
-
const { result } = renderHook(() =>
|
|
482
|
-
useHasPermission('user-123', scope, 'read:users')
|
|
483
|
-
);
|
|
484
|
-
|
|
485
|
-
await waitFor(() => {
|
|
486
|
-
expect(result.current.hasPermission).toBe(true);
|
|
487
|
-
});
|
|
488
|
-
});
|
|
489
|
-
});
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
## 🎨 Component-Specific Patterns
|
|
493
|
-
|
|
494
|
-
### DataTable Testing Strategy
|
|
495
|
-
|
|
496
|
-
DataTable subcomponents intentionally have low unit test coverage because they're comprehensively tested through integration tests. This is **correct and intentional**.
|
|
497
|
-
|
|
498
|
-
```typescript
|
|
499
|
-
// ✅ Good - Integration test for DataTable workflows
|
|
500
|
-
describe('DataTable - Complete Workflow', () => {
|
|
501
|
-
it('allows editing, sorting, and filtering data', async () => {
|
|
502
|
-
const user = userEvent.setup();
|
|
503
|
-
|
|
504
|
-
render(<DataTable data={mockData} onSave={mockSave} />);
|
|
505
|
-
|
|
506
|
-
// Test editing
|
|
507
|
-
await user.click(screen.getByRole('button', { name: 'Edit' }));
|
|
508
|
-
await user.type(screen.getByRole('textbox'), 'Updated Value');
|
|
509
|
-
await user.click(screen.getByRole('button', { name: 'Save' }));
|
|
510
|
-
|
|
511
|
-
// Test sorting
|
|
512
|
-
await user.click(screen.getByRole('columnheader', { name: 'Name' }));
|
|
513
|
-
|
|
514
|
-
// Test filtering
|
|
515
|
-
await user.type(screen.getByPlaceholderText('Filter...'), 'search term');
|
|
516
|
-
|
|
517
|
-
expect(mockSave).toHaveBeenCalledWith(expectedData);
|
|
518
|
-
});
|
|
519
|
-
});
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
### Service Hook Testing
|
|
523
|
-
|
|
524
|
-
```typescript
|
|
525
|
-
describe('useEventService', () => {
|
|
526
|
-
it('throws error when used outside provider', () => {
|
|
527
|
-
expect(() => {
|
|
528
|
-
renderHook(() => useEventService());
|
|
529
|
-
}).toThrow('useEventService must be used within EventServiceProvider');
|
|
530
|
-
});
|
|
531
|
-
|
|
532
|
-
it('subscribes to service updates and cleans up', () => {
|
|
533
|
-
const unsubscribe = vi.fn();
|
|
534
|
-
const mockService = {
|
|
535
|
-
subscribe: vi.fn(() => unsubscribe)
|
|
536
|
-
};
|
|
537
|
-
|
|
538
|
-
const { unmount } = renderHook(() => useEventService(), {
|
|
539
|
-
wrapper: ({ children }) => (
|
|
540
|
-
<EventServiceContext.Provider value={{ eventService: mockService }}>
|
|
541
|
-
{children}
|
|
542
|
-
</EventServiceContext.Provider>
|
|
543
|
-
)
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
expect(mockService.subscribe).toHaveBeenCalled();
|
|
547
|
-
|
|
548
|
-
unmount();
|
|
549
|
-
expect(unsubscribe).toHaveBeenCalled();
|
|
550
|
-
});
|
|
551
|
-
});
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
## ⚡ Performance & Memory
|
|
555
|
-
|
|
556
|
-
### Memory Leak Prevention
|
|
557
|
-
|
|
558
|
-
```typescript
|
|
559
|
-
describe('Component with Async Operations', () => {
|
|
560
|
-
beforeEach(() => {
|
|
561
|
-
vi.useFakeTimers();
|
|
562
|
-
});
|
|
563
|
-
|
|
564
|
-
afterEach(() => {
|
|
565
|
-
// Prevent memory leaks
|
|
566
|
-
vi.clearAllTimers();
|
|
567
|
-
vi.useRealTimers();
|
|
568
|
-
cleanup();
|
|
569
|
-
vi.clearAllMocks();
|
|
570
|
-
localStorage.clear();
|
|
571
|
-
sessionStorage.clear();
|
|
572
|
-
});
|
|
573
|
-
|
|
574
|
-
it('handles cleanup properly', async () => {
|
|
575
|
-
// Test implementation
|
|
576
|
-
});
|
|
577
|
-
});
|
|
578
|
-
```
|
|
579
|
-
|
|
580
|
-
### Async Testing Guidelines
|
|
581
|
-
|
|
582
|
-
```typescript
|
|
583
|
-
// ✅ Good - Appropriate timeouts based on operation speed
|
|
584
|
-
await waitFor(() => {
|
|
585
|
-
expect(result.current.isLoading).toBe(false);
|
|
586
|
-
}, { timeout: 100, interval: 10 }); // Fast operations
|
|
587
|
-
|
|
588
|
-
await waitFor(() => {
|
|
589
|
-
expect(result.current.data).toBeDefined();
|
|
590
|
-
}, { timeout: 2000 }); // Most async operations (2-3 seconds)
|
|
591
|
-
|
|
592
|
-
// ⚠️ Only use 5+ seconds for truly slow operations
|
|
593
|
-
await waitFor(() => {
|
|
594
|
-
expect(result.current.data).toBeDefined();
|
|
595
|
-
}, { timeout: 5000 }); // Network calls, complex computations only
|
|
596
|
-
```
|
|
597
|
-
|
|
598
|
-
**Timeout Guidelines**:
|
|
599
|
-
- **Fast operations** (< 100ms): `timeout: 100-500`
|
|
600
|
-
- **Standard async** (100ms-2s): `timeout: 2000-3000`
|
|
601
|
-
- **Slow operations** (2s+): `timeout: 5000+` (with documentation)
|
|
602
|
-
|
|
603
|
-
**Avoid**:
|
|
604
|
-
- ❌ Using 5-6 second timeouts for mock operations that resolve immediately
|
|
605
|
-
- ❌ Using `waitFor` for synchronous operations
|
|
606
|
-
- ❌ Unnecessary delays in mock implementations
|
|
607
|
-
|
|
608
|
-
## 🔧 Test Configuration
|
|
609
|
-
|
|
610
|
-
### Vitest Configuration
|
|
611
|
-
|
|
612
|
-
```typescript
|
|
613
|
-
// vitest.config.ts
|
|
614
|
-
export default defineConfig({
|
|
615
|
-
test: {
|
|
616
|
-
environment: 'jsdom',
|
|
617
|
-
environmentOptions: {
|
|
618
|
-
jsdom: {
|
|
619
|
-
pretendToBeVisual: true, // Enables getComputedStyle
|
|
620
|
-
resources: 'usable' // Enables resource loading
|
|
621
|
-
}
|
|
622
|
-
},
|
|
623
|
-
coverage: {
|
|
624
|
-
thresholds: {
|
|
625
|
-
lines: 82,
|
|
626
|
-
branches: 80,
|
|
627
|
-
functions: 80,
|
|
628
|
-
statements: 82
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
});
|
|
633
|
-
```
|
|
634
|
-
|
|
635
|
-
### Test Utilities Setup
|
|
636
|
-
|
|
637
|
-
```typescript
|
|
638
|
-
// test-utils.tsx
|
|
639
|
-
export function renderWithProviders(
|
|
640
|
-
ui: React.ReactElement,
|
|
641
|
-
options: { organisationId?: string } = {}
|
|
642
|
-
) {
|
|
643
|
-
function Wrapper({ children }: { children: React.ReactNode }) {
|
|
644
|
-
return (
|
|
645
|
-
<OrganisationProvider organisationId={options.organisationId}>
|
|
646
|
-
<RBACProvider>
|
|
647
|
-
{children}
|
|
648
|
-
</RBACProvider>
|
|
649
|
-
</OrganisationProvider>
|
|
650
|
-
);
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
return render(ui, { wrapper: Wrapper, ...options });
|
|
654
|
-
}
|
|
655
|
-
```
|
|
656
|
-
|
|
657
|
-
## 🚀 Running Tests
|
|
658
|
-
|
|
659
|
-
### Commands
|
|
660
|
-
|
|
661
|
-
```bash
|
|
662
|
-
# Run all tests
|
|
663
|
-
npm test
|
|
664
|
-
|
|
665
|
-
# Run with coverage
|
|
666
|
-
npm test -- --coverage
|
|
667
|
-
|
|
668
|
-
# Run specific test file
|
|
669
|
-
npm test -- Button.test.tsx
|
|
670
|
-
|
|
671
|
-
# Run tests in watch mode
|
|
672
|
-
npm test -- --watch
|
|
673
|
-
|
|
674
|
-
# Run tests with timeout (prevents hanging)
|
|
675
|
-
timeout 60 npm test
|
|
676
|
-
```
|
|
677
|
-
|
|
678
|
-
### Debugging
|
|
679
|
-
|
|
680
|
-
```typescript
|
|
681
|
-
// Debug output
|
|
682
|
-
screen.debug();
|
|
683
|
-
|
|
684
|
-
// Debug specific element
|
|
685
|
-
screen.debug(screen.getByRole('button'));
|
|
686
|
-
|
|
687
|
-
// Log available queries
|
|
688
|
-
screen.logTestingPlaygroundURL();
|
|
689
|
-
```
|
|
690
|
-
|
|
691
|
-
## 📋 Pre-Merge Checklist
|
|
692
|
-
|
|
693
|
-
- [ ] All tests pass without `it.only` or `test.skip` (see Skipped Test Policy below)
|
|
694
|
-
- [ ] Coverage thresholds are met
|
|
695
|
-
- [ ] Tests use semantic queries (avoid test IDs)
|
|
696
|
-
- [ ] Async operations use proper waiting patterns
|
|
697
|
-
- [ ] Mocks are cleaned up in `afterEach`
|
|
698
|
-
- [ ] Tests focus on behavior, not implementation
|
|
699
|
-
- [ ] Error scenarios are covered
|
|
700
|
-
- [ ] Tests are colocated with source files
|
|
701
|
-
- [ ] Timeout values are appropriate (see Performance Guidelines below)
|
|
702
|
-
|
|
703
|
-
## 🎯 Test Categories & Tags
|
|
704
|
-
|
|
705
|
-
Use explicit tags for test organization:
|
|
706
|
-
|
|
707
|
-
```typescript
|
|
708
|
-
describe('[unit] useDebounce', () => {
|
|
709
|
-
it('delays function execution', () => {});
|
|
710
|
-
});
|
|
711
|
-
|
|
712
|
-
describe('[component] Button', () => {
|
|
713
|
-
it('renders with correct styling', () => {});
|
|
714
|
-
});
|
|
715
|
-
|
|
716
|
-
describe('[integration] User Registration', () => {
|
|
717
|
-
it('completes full signup flow', () => {});
|
|
718
|
-
});
|
|
719
|
-
```
|
|
720
|
-
|
|
721
|
-
## 📚 Resources
|
|
722
|
-
|
|
723
|
-
### Documentation
|
|
724
|
-
- [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/)
|
|
725
|
-
- [Vitest Documentation](https://vitest.dev/)
|
|
726
|
-
- [Jest DOM Matchers](https://github.com/testing-library/jest-dom)
|
|
727
|
-
|
|
728
|
-
### Internal Guides
|
|
729
|
-
- [Documentation Standard](../../docs/DOCUMENTATION_STANDARD.md)
|
|
730
|
-
- [Memory Performance Analysis](../../../MEMORY_PERFORMANCE_ANALYSIS.md)
|
|
731
|
-
- [Test Failure Analysis](../../../TEST_FAILURE_ANALYSIS.md)
|
|
732
|
-
|
|
733
|
-
---
|
|
734
|
-
|
|
735
|
-
## 🎖️ Excellence Indicators
|
|
736
|
-
|
|
737
|
-
A world-class test suite demonstrates:
|
|
738
|
-
|
|
739
|
-
- **Comprehensive Coverage** - All critical paths tested
|
|
740
|
-
- **Behavioral Focus** - Tests what users experience
|
|
741
|
-
- **Maintainable Structure** - Easy to update and extend
|
|
742
|
-
- **Fast Execution** - Quick feedback loops
|
|
743
|
-
- **Clear Intent** - Tests serve as living documentation
|
|
744
|
-
- **Reliable Results** - Consistent across environments
|
|
745
|
-
- **Accessibility Awareness** - Tests include a11y considerations
|
|
746
|
-
|
|
747
|
-
Remember: **Tests are not just about catching bugs—they're about building confidence, enabling refactoring, and documenting expected behavior for future developers.**
|
|
748
|
-
|
|
749
|
-
---
|
|
750
|
-
|
|
751
|
-
## 🔄 Skipped Test Policy
|
|
752
|
-
|
|
753
|
-
### When to Skip Tests
|
|
754
|
-
|
|
755
|
-
**✅ Appropriate Reasons**:
|
|
756
|
-
- Feature is planned but not yet implemented
|
|
757
|
-
- Test documents future feature requirements
|
|
758
|
-
- Feature is blocked by dependencies
|
|
759
|
-
- Test is for experimental/optional feature
|
|
760
|
-
|
|
761
|
-
**❌ Inappropriate Reasons**:
|
|
762
|
-
- Test is flaky (fix the test instead)
|
|
763
|
-
- Test is slow (optimize instead)
|
|
764
|
-
- Feature is deprecated (remove test)
|
|
765
|
-
- Test is temporarily broken (fix immediately)
|
|
766
|
-
|
|
767
|
-
### Requirements for Skipped Tests
|
|
768
|
-
|
|
769
|
-
1. **Clear Documentation**: Add comment explaining why test is skipped
|
|
770
|
-
2. **Reference Tracking**: Link to feature issue or ticket
|
|
771
|
-
3. **Expected Timeline**: Include expected implementation date (if known)
|
|
772
|
-
4. **Quarterly Review**: Review skipped tests quarterly to determine if still relevant
|
|
773
|
-
|
|
774
|
-
### Example
|
|
775
|
-
|
|
776
|
-
```typescript
|
|
777
|
-
// TODO: Enable when keyboard navigation is implemented
|
|
778
|
-
// See: https://github.com/org/repo/issues/123
|
|
779
|
-
// Expected: Q2 2025
|
|
780
|
-
it.skip('should navigate between headers with arrow keys', async () => {
|
|
781
|
-
// Test implementation
|
|
782
|
-
});
|
|
783
|
-
```
|
|
784
|
-
|
|
785
|
-
### Skipped Test Review Process
|
|
786
|
-
|
|
787
|
-
1. **Quarterly Audit**: Review all skipped tests
|
|
788
|
-
2. **Decision Matrix**:
|
|
789
|
-
- Feature implemented → Enable test
|
|
790
|
-
- Feature cancelled → Remove test
|
|
791
|
-
- Feature deferred → Update timeline
|
|
792
|
-
- Still relevant → Keep skipped with updated timeline
|
|
793
|
-
3. **Documentation**: Update test comments with current status
|
|
794
|
-
|
|
795
|
-
---
|
|
796
|
-
|
|
797
|
-
## 📊 Coverage Gap Remediation
|
|
798
|
-
|
|
799
|
-
### Coverage Thresholds
|
|
800
|
-
|
|
801
|
-
| Category | Target | CI Blocking | Rationale |
|
|
802
|
-
|----------|--------|-------------|-----------|
|
|
803
|
-
| **Utils/Hooks** | 95% | Yes | Core business logic, high reuse |
|
|
804
|
-
| **UI Components** | 90% | Yes | User-facing, must be reliable |
|
|
805
|
-
| **Services** | 85% | Yes | API interactions, critical paths |
|
|
806
|
-
| **Validation** | 95% | Yes | Security and data integrity |
|
|
807
|
-
| **Overall Project** | 80% | Yes | Quality baseline |
|
|
808
|
-
|
|
809
|
-
### Identifying Coverage Gaps
|
|
810
|
-
|
|
811
|
-
1. **Run Coverage Report**:
|
|
812
|
-
```bash
|
|
813
|
-
npm test -- --coverage
|
|
814
|
-
```
|
|
815
|
-
|
|
816
|
-
2. **Review Coverage Report**:
|
|
817
|
-
- Check per-file coverage percentages
|
|
818
|
-
- Identify files below thresholds
|
|
819
|
-
- Review uncovered lines/branches
|
|
820
|
-
|
|
821
|
-
3. **Prioritize Gaps**:
|
|
822
|
-
- **Critical**: RBAC, auth, services
|
|
823
|
-
- **High**: Business logic, hooks
|
|
824
|
-
- **Medium**: UI components, utilities
|
|
825
|
-
- **Low**: Type definitions, simple utilities
|
|
826
|
-
|
|
827
|
-
### Remediation Process
|
|
828
|
-
|
|
829
|
-
1. **Analyze Gap**: Understand what's not covered
|
|
830
|
-
2. **Create Test Plan**: Determine test type (unit, integration)
|
|
831
|
-
3. **Write Tests**: Follow TEST_STANDARD.md patterns
|
|
832
|
-
4. **Verify Coverage**: Run coverage report to confirm improvement
|
|
833
|
-
5. **Document**: Add comments for complex test scenarios
|
|
834
|
-
|
|
835
|
-
### Coverage Improvement Checklist
|
|
836
|
-
|
|
837
|
-
- [ ] Identify files below thresholds
|
|
838
|
-
- [ ] Prioritize critical paths
|
|
839
|
-
- [ ] Create test plan for each file
|
|
840
|
-
- [ ] Write tests following TEST_STANDARD.md
|
|
841
|
-
- [ ] Verify coverage improvement
|
|
842
|
-
- [ ] Document complex test scenarios
|
|
843
|
-
|
|
844
|
-
---
|
|
845
|
-
|
|
846
|
-
## ⚡ Performance Test Guidelines
|
|
847
|
-
|
|
848
|
-
### Test Execution Time Targets
|
|
849
|
-
|
|
850
|
-
- **Unit Tests**: < 50ms average
|
|
851
|
-
- **Component Tests**: < 100ms average
|
|
852
|
-
- **Integration Tests**: < 500ms average
|
|
853
|
-
- **E2E Tests**: < 2s average
|
|
854
|
-
|
|
855
|
-
### Timeout Best Practices
|
|
856
|
-
|
|
857
|
-
**Standard Timeouts**:
|
|
858
|
-
- Fast operations: `timeout: 100-500`
|
|
859
|
-
- Standard async: `timeout: 2000-3000`
|
|
860
|
-
- Slow operations: `timeout: 5000+` (with documentation)
|
|
861
|
-
|
|
862
|
-
**Optimization Tips**:
|
|
863
|
-
1. Use immediate mock resolution when possible
|
|
864
|
-
2. Avoid unnecessary `setTimeout` in mocks
|
|
865
|
-
3. Use `findBy` queries instead of `waitFor` + `getBy`
|
|
866
|
-
4. Reduce timeout values for fast operations
|
|
867
|
-
|
|
868
|
-
### Performance Testing Best Practices
|
|
869
|
-
|
|
870
|
-
**When to Test Performance**:
|
|
871
|
-
- ✅ Critical user-facing operations (rendering, navigation)
|
|
872
|
-
- ✅ Operations that must complete within SLA
|
|
873
|
-
- ✅ Memory-intensive operations
|
|
874
|
-
- ❌ Avoid testing performance of mocked operations
|
|
875
|
-
- ❌ Avoid absolute timing thresholds in CI environments
|
|
876
|
-
|
|
877
|
-
**Performance Test Patterns**:
|
|
878
|
-
|
|
879
|
-
```typescript
|
|
880
|
-
// ❌ Bad: Absolute thresholds (brittle in CI/coverage)
|
|
881
|
-
const startTime = performance.now();
|
|
882
|
-
render(<Component />);
|
|
883
|
-
const endTime = performance.now();
|
|
884
|
-
expect(endTime - startTime).toBeLessThan(200); // Fails under coverage
|
|
885
|
-
|
|
886
|
-
// ✅ Good: Behavioral assertions (focus on outcomes)
|
|
887
|
-
await waitFor(() => {
|
|
888
|
-
expect(screen.getByRole('navigation')).toBeInTheDocument();
|
|
889
|
-
}, { timeout: 2000 });
|
|
890
|
-
|
|
891
|
-
// ✅ Good: Relative comparisons (more tolerant)
|
|
892
|
-
const baseline = measureBaseline();
|
|
893
|
-
const actual = measureActual();
|
|
894
|
-
expect(actual).toBeLessThan(baseline * 1.5); // 50% tolerance
|
|
895
|
-
|
|
896
|
-
// ✅ Good: Smoke tests (verify no regressions)
|
|
897
|
-
it('renders without performance degradation', async () => {
|
|
898
|
-
const startTime = performance.now();
|
|
899
|
-
render(<Component />);
|
|
900
|
-
await waitFor(() => {
|
|
901
|
-
expect(screen.getByRole('main')).toBeInTheDocument();
|
|
902
|
-
});
|
|
903
|
-
const endTime = performance.now();
|
|
904
|
-
// Only fail if significantly slower (e.g., > 5s)
|
|
905
|
-
expect(endTime - startTime).toBeLessThan(5000);
|
|
906
|
-
});
|
|
907
|
-
```
|
|
908
|
-
|
|
909
|
-
**Performance Test Guidelines**:
|
|
910
|
-
1. **Prefer Behavioral Tests**: Focus on what users see, not raw timing
|
|
911
|
-
2. **Use Relative Thresholds**: Compare against baseline, not absolute values
|
|
912
|
-
3. **Skip in Coverage Mode**: Use `if (process.env.COVERAGE) return;` for timing tests
|
|
913
|
-
4. **Document Thresholds**: Explain why specific timing is critical
|
|
914
|
-
5. **Separate Performance Suite**: Consider separate test suite for performance tests
|
|
915
|
-
|
|
916
|
-
### Memory Management
|
|
917
|
-
|
|
918
|
-
```typescript
|
|
919
|
-
describe('Component with Resources', () => {
|
|
920
|
-
beforeEach(() => {
|
|
921
|
-
vi.useFakeTimers();
|
|
922
|
-
});
|
|
923
|
-
|
|
924
|
-
afterEach(() => {
|
|
925
|
-
// Prevent memory leaks
|
|
926
|
-
vi.clearAllTimers();
|
|
927
|
-
vi.useRealTimers();
|
|
928
|
-
cleanup();
|
|
929
|
-
vi.clearAllMocks();
|
|
930
|
-
localStorage.clear();
|
|
931
|
-
sessionStorage.clear();
|
|
932
|
-
});
|
|
933
|
-
});
|
|
934
|
-
```
|
|
935
|
-
|
|
936
|
-
### Performance Monitoring
|
|
937
|
-
|
|
938
|
-
- Monitor test execution times in CI
|
|
939
|
-
- Track slow tests (> 100ms)
|
|
940
|
-
- Alert on tests exceeding thresholds
|
|
941
|
-
- Review and optimize slow tests regularly
|
|
942
|
-
|
|
943
|
-
---
|
|
944
|
-
|
|
945
|
-
## 📁 Large Test File Management
|
|
946
|
-
|
|
947
|
-
### When to Split Test Files
|
|
948
|
-
|
|
949
|
-
**Consider Splitting When**:
|
|
950
|
-
- File exceeds 800 lines
|
|
951
|
-
- File contains multiple distinct feature areas
|
|
952
|
-
- File has slow execution times
|
|
953
|
-
- File is difficult to navigate
|
|
954
|
-
|
|
955
|
-
### Splitting Strategy
|
|
956
|
-
|
|
957
|
-
**By Feature Area**:
|
|
958
|
-
```
|
|
959
|
-
Component.test.tsx → Component.rendering.test.tsx
|
|
960
|
-
→ Component.interactions.test.tsx
|
|
961
|
-
→ Component.state.test.tsx
|
|
962
|
-
```
|
|
963
|
-
|
|
964
|
-
**By Test Type**:
|
|
965
|
-
```
|
|
966
|
-
Component.test.tsx → Component.unit.test.tsx
|
|
967
|
-
→ Component.integration.test.tsx
|
|
968
|
-
→ Component.accessibility.test.tsx
|
|
969
|
-
```
|
|
970
|
-
|
|
971
|
-
### Splitting Guidelines
|
|
972
|
-
|
|
973
|
-
1. **Keep Related Tests Together**: Don't split if tests are tightly coupled
|
|
974
|
-
2. **Maintain Test Organization**: Use describe blocks for organization
|
|
975
|
-
3. **Share Test Utilities**: Extract shared setup to test utilities
|
|
976
|
-
4. **Document Structure**: Add README explaining test organization
|
|
977
|
-
|
|
978
|
-
### File Size Recommendations
|
|
979
|
-
|
|
980
|
-
- **< 500 lines**: No splitting needed
|
|
981
|
-
- **500-800 lines**: Consider if organization improves
|
|
982
|
-
- **> 800 lines**: Strongly consider splitting
|
|
983
|
-
- **> 1000 lines**: Should be split
|
|
984
|
-
|
|
985
|
-
---
|
|
986
|
-
|
|
987
|
-
## 📈 Continuous Improvement
|
|
988
|
-
|
|
989
|
-
### Regular Reviews
|
|
990
|
-
|
|
991
|
-
1. **Quarterly**: Review skipped tests, coverage gaps, slow tests
|
|
992
|
-
2. **Monthly**: Review test execution times and patterns
|
|
993
|
-
3. **Per PR**: Ensure new tests follow TEST_STANDARD.md
|
|
994
|
-
|
|
995
|
-
### Metrics to Track
|
|
996
|
-
|
|
997
|
-
- Test execution time trends
|
|
998
|
-
- Coverage percentage trends
|
|
999
|
-
- Number of skipped tests
|
|
1000
|
-
- Test helper usage patterns
|
|
1001
|
-
- Test file sizes
|
|
1002
|
-
|
|
1003
|
-
### Resources
|
|
1004
|
-
|
|
1005
|
-
- [Coverage Gap Analysis](../../docs/testing/coverage-gap-analysis.md)
|
|
1006
|
-
- [Test Quality Audit](../../docs/testing/test-quality-audit.md)
|
|
1007
|
-
- [Test Helpers Audit](../../docs/testing/test-helpers-audit.md)
|
|
1008
|
-
- [Skipped Tests Analysis](../../docs/testing/skipped-tests-analysis.md)
|