@jmruthers/pace-core 0.5.183 → 0.5.185
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 +38 -0
- package/README.md +60 -1
- package/core-usage-manifest.json +312 -0
- package/dist/{DataTable-QAB34V6K.js → DataTable-IX2NBUTP.js} +6 -6
- package/dist/{DataTable-Bz8ffqyA.d.ts → DataTable-Z9NLVJh0.d.ts} +1 -1
- package/dist/{index-Bl--n7-T.d.ts → PublicPageProvider-BABf6JCh.d.ts} +21 -10
- package/dist/{UnifiedAuthProvider-7F6T4B6K.js → UnifiedAuthProvider-A4BCQRJY.js} +4 -2
- package/dist/{UnifiedAuthProvider-F86d7dSi.d.ts → UnifiedAuthProvider-BG0AL5eE.d.ts} +2 -1
- package/dist/{api-ROMBCNKU.js → api-BMFCXVQX.js} +2 -2
- package/dist/{chunk-RA3JUFMW.js → chunk-445GEP27.js} +154 -4
- package/dist/{chunk-RA3JUFMW.js.map → chunk-445GEP27.js.map} +1 -1
- package/dist/{chunk-CSOFYHAG.js → chunk-AISXLWGZ.js} +374 -60
- package/dist/chunk-AISXLWGZ.js.map +1 -0
- package/dist/{chunk-FUEYYMX5.js → chunk-FXFJRTKI.js} +24 -3
- package/dist/chunk-FXFJRTKI.js.map +1 -0
- package/dist/{chunk-QETLRQI6.js → chunk-HC67NW5K.js} +380 -360
- package/dist/chunk-HC67NW5K.js.map +1 -0
- package/dist/chunk-HESYZWZW.js +388 -0
- package/dist/chunk-HESYZWZW.js.map +1 -0
- package/dist/{chunk-QUVSNGIP.js → chunk-HGPQUCBC.js} +34 -9
- package/dist/{chunk-QUVSNGIP.js.map → chunk-HGPQUCBC.js.map} +1 -1
- package/dist/{chunk-UHNYIBXL.js → chunk-IXSNYUCT.js} +1 -1
- package/dist/chunk-IXSNYUCT.js.map +1 -0
- package/dist/{chunk-MI7HBHN3.js → chunk-MX3EIJGQ.js} +4 -3
- package/dist/{chunk-MI7HBHN3.js.map → chunk-MX3EIJGQ.js.map} +1 -1
- package/dist/{chunk-PWAHJW4G.js → chunk-OKI34GZD.js} +86 -33
- package/dist/chunk-OKI34GZD.js.map +1 -0
- package/dist/{chunk-W22JP75J.js → chunk-STTZQK2I.js} +3 -3
- package/dist/chunk-THRPYOFK.js +215 -0
- package/dist/chunk-THRPYOFK.js.map +1 -0
- package/dist/{chunk-M7W4CP3M.js → chunk-U6WNSFX5.js} +2 -1
- package/dist/chunk-U6WNSFX5.js.map +1 -0
- package/dist/{chunk-QCDXODCA.js → chunk-XAUHJD3L.js} +2 -2
- package/dist/components.d.ts +182 -6
- package/dist/components.js +157 -11
- package/dist/components.js.map +1 -1
- package/dist/eslint-rules/pace-core-compliance.cjs +406 -0
- package/dist/{file-reference-D06mEEWW.d.ts → file-reference-BjR39ktt.d.ts} +7 -1
- package/dist/hooks.d.ts +7 -14
- package/dist/hooks.js +10 -22
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +11 -11
- package/dist/index.js +79 -16
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +3 -1
- package/dist/rbac/index.d.ts +205 -14
- package/dist/rbac/index.js +28 -6
- package/dist/timezone-_pgH8qrY.d.ts +530 -0
- package/dist/{types-_x1f4QBF.d.ts → types-DUyCRSTj.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/{usePublicRouteParams-JJczomYq.d.ts → usePublicRouteParams-CvnC3d-e.d.ts} +113 -2
- package/dist/utils.d.ts +109 -151
- package/dist/utils.js +128 -138
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +60 -1
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/Logger.md +178 -0
- 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/RBACAuditManager.md +2 -2
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +2 -2
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +5 -5
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +54 -0
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CalendarProps.md +18 -2
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +30 -0
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/DatabaseComplianceResult.md +85 -0
- package/docs/api/interfaces/DatabaseIssue.md +41 -0
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +6 -6
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +24 -8
- package/docs/api/interfaces/FileUploadProps.md +24 -13
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +1 -1
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +9 -9
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +62 -0
- 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 +36 -23
- 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 +11 -11
- 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 +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/QuickFix.md +52 -0
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +4 -4
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +7 -7
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +5 -5
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/RuntimeComplianceResult.md +55 -0
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- package/docs/api/interfaces/SetupIssue.md +41 -0
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +1 -1
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseFormDialogOptions.md +62 -0
- package/docs/api/interfaces/UseFormDialogReturn.md +117 -0
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +738 -42
- package/docs/api-reference/hooks.md +111 -0
- package/docs/api-reference/rpc-functions.md +1 -1
- package/docs/api-reference/utilities.md +184 -0
- package/docs/getting-started/installation-guide.md +75 -16
- package/docs/getting-started/quick-start.md +61 -11
- package/docs/implementation-guides/authentication.md +88 -12
- package/docs/implementation-guides/file-reference-system.md +2 -1
- package/docs/implementation-guides/file-upload-storage.md +21 -0
- package/docs/rbac/README.md +1 -0
- package/docs/rbac/compliance/compliance-guide.md +544 -0
- package/docs/rbac/getting-started.md +158 -33
- package/docs/standards/pace-core-compliance.md +432 -0
- package/eslint-config-pace-core.cjs +93 -0
- package/package.json +15 -3
- package/scripts/analyze-bundle.js +232 -0
- package/scripts/build-css.js +56 -0
- package/scripts/build-docs-incremental.js +1015 -0
- package/scripts/check-pace-core-compliance.cjs +2353 -0
- package/scripts/generate-docs.js +157 -0
- package/scripts/setup-build-cache.js +73 -0
- package/scripts/utils/command-runner.js +131 -0
- package/scripts/utils/env.js +33 -0
- package/scripts/utils/index.js +10 -0
- package/scripts/utils/logger.js +88 -0
- package/scripts/utils/path-helpers.js +37 -0
- package/scripts/validate-formats.js +133 -0
- package/scripts/validate-master.js +155 -0
- package/scripts/validate-pre-publish.js +140 -0
- package/scripts/validate-theme.js +142 -0
- package/src/components/Calendar/Calendar.tsx +8 -1
- package/src/components/Card/Card.tsx +47 -8
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +314 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +126 -0
- package/src/components/DatePickerWithTimezone/README.md +135 -0
- package/src/components/DatePickerWithTimezone/index.ts +10 -0
- package/src/components/DateTimeField/DateTimeField.test.tsx +358 -0
- package/src/components/DateTimeField/DateTimeField.tsx +232 -0
- package/src/components/DateTimeField/README.md +148 -0
- package/src/components/DateTimeField/index.ts +10 -0
- package/src/components/FileUpload/FileUpload.tsx +3 -0
- package/src/components/Header/Header.test.tsx +47 -18
- package/src/components/Header/Header.tsx +24 -6
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +29 -20
- package/src/components/PaceAppLayout/README.md +9 -0
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +37 -8
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +12 -4
- package/src/components/index.ts +8 -0
- package/src/eslint-rules/pace-core-compliance.cjs +406 -0
- package/src/eslint-rules/pace-core-compliance.js +640 -0
- package/src/hooks/__tests__/useFormDialog.test.ts +478 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useFileReference.test.ts +1 -0
- package/src/hooks/useFormDialog.ts +147 -0
- package/src/index.ts +27 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +6 -5
- package/src/providers/services/UnifiedAuthProvider.tsx +24 -3
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +3 -0
- package/src/rbac/compliance/database-validator.ts +165 -0
- package/src/rbac/compliance/index.ts +38 -0
- package/src/rbac/compliance/quick-fix-suggestions.ts +209 -0
- package/src/rbac/compliance/runtime-compliance.ts +77 -0
- package/src/rbac/compliance/setup-validator.ts +131 -0
- package/src/rbac/components/PagePermissionGuard.tsx +8 -64
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +35 -21
- package/src/rbac/docs/event-based-apps.md +285 -0
- package/src/rbac/errors.ts +11 -0
- package/src/rbac/hooks/useRoleManagement.ts +292 -12
- package/src/rbac/index.ts +30 -0
- package/src/services/OrganisationService.ts +4 -0
- package/src/types/file-reference.ts +6 -0
- package/src/utils/__tests__/timezone.test.ts +345 -0
- package/src/utils/file-reference/__tests__/file-reference.test.ts +2 -0
- package/src/utils/file-reference/index.ts +1 -0
- package/src/utils/formatting/formatDateTimeTimezone.test.ts +167 -0
- package/src/utils/formatting/formatting.ts +179 -0
- package/src/utils/index.ts +27 -1
- package/src/utils/location/index.ts +16 -0
- package/src/utils/location/location.test.ts +286 -0
- package/src/utils/location/location.ts +175 -0
- package/src/utils/timezone/index.ts +17 -0
- package/src/utils/timezone/timezone.test.ts +349 -0
- package/src/utils/timezone/timezone.ts +281 -0
- package/dist/chunk-CSOFYHAG.js.map +0 -1
- package/dist/chunk-FUEYYMX5.js.map +0 -1
- package/dist/chunk-HKIT6O7W.js +0 -198
- package/dist/chunk-HKIT6O7W.js.map +0 -1
- package/dist/chunk-KUEN3HFB.js +0 -94
- package/dist/chunk-KUEN3HFB.js.map +0 -1
- package/dist/chunk-M7W4CP3M.js.map +0 -1
- package/dist/chunk-PWAHJW4G.js.map +0 -1
- package/dist/chunk-QETLRQI6.js.map +0 -1
- package/dist/chunk-UHNYIBXL.js.map +0 -1
- package/dist/formatting-5wETwiGF.d.ts +0 -162
- /package/dist/{DataTable-QAB34V6K.js.map → DataTable-IX2NBUTP.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-7F6T4B6K.js.map → UnifiedAuthProvider-A4BCQRJY.js.map} +0 -0
- /package/dist/{api-ROMBCNKU.js.map → api-BMFCXVQX.js.map} +0 -0
- /package/dist/{chunk-W22JP75J.js.map → chunk-STTZQK2I.js.map} +0 -0
- /package/dist/{chunk-QCDXODCA.js.map → chunk-XAUHJD3L.js.map} +0 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Timezone Utilities Unit Tests
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Utils/__tests__/Timezone
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* Comprehensive tests for timezone utility functions covering all critical functionality,
|
|
8
|
+
* edge cases, and error handling.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
12
|
+
import {
|
|
13
|
+
formatInTimeZone,
|
|
14
|
+
getTimezoneAbbreviation,
|
|
15
|
+
formatTimeInTimeZone,
|
|
16
|
+
getUserTimeZone,
|
|
17
|
+
toZonedTime,
|
|
18
|
+
fromZonedTime,
|
|
19
|
+
roundToNearestMinutes,
|
|
20
|
+
getTimeZoneDifference
|
|
21
|
+
} from '../timezone';
|
|
22
|
+
|
|
23
|
+
describe('Timezone Utilities', () => {
|
|
24
|
+
describe('formatInTimeZone', () => {
|
|
25
|
+
it('should format date in specific timezone', () => {
|
|
26
|
+
const utcDate = new Date('2024-01-15T10:00:00Z');
|
|
27
|
+
const result = formatInTimeZone(utcDate, 'America/New_York', 'MMM dd, yyyy HH:mm');
|
|
28
|
+
|
|
29
|
+
// EST is UTC-5, so 10:00 UTC = 05:00 EST
|
|
30
|
+
expect(result).toContain('Jan 15, 2024');
|
|
31
|
+
expect(result).toContain('05:00');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should handle ISO string input', () => {
|
|
35
|
+
const result = formatInTimeZone('2024-01-15T10:00:00Z', 'America/New_York', 'MMM dd, yyyy');
|
|
36
|
+
expect(result).toContain('Jan 15, 2024');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should handle timestamp input', () => {
|
|
40
|
+
const timestamp = new Date('2024-01-15T10:00:00Z').getTime();
|
|
41
|
+
const result = formatInTimeZone(timestamp, 'America/New_York', 'MMM dd, yyyy');
|
|
42
|
+
expect(result).toContain('Jan 15, 2024');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should handle different format strings', () => {
|
|
46
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
47
|
+
const result = formatInTimeZone(date, 'America/New_York', 'yyyy-MM-dd');
|
|
48
|
+
expect(result).toBe('2024-01-15');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should return "Invalid date" for invalid date input', () => {
|
|
52
|
+
const result = formatInTimeZone(new Date('invalid'), 'America/New_York', 'MMM dd, yyyy');
|
|
53
|
+
expect(result).toBe('Invalid date');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should return "Invalid date" for invalid timezone', () => {
|
|
57
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
58
|
+
const result = formatInTimeZone(date, '', 'MMM dd, yyyy');
|
|
59
|
+
expect(result).toBe('Invalid date');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should handle DST transitions', () => {
|
|
63
|
+
// Summer date (DST)
|
|
64
|
+
const summerDate = new Date('2024-07-15T10:00:00Z');
|
|
65
|
+
const summerResult = formatInTimeZone(summerDate, 'America/New_York', 'HH:mm');
|
|
66
|
+
|
|
67
|
+
// Winter date (no DST)
|
|
68
|
+
const winterDate = new Date('2024-01-15T10:00:00Z');
|
|
69
|
+
const winterResult = formatInTimeZone(winterDate, 'America/New_York', 'HH:mm');
|
|
70
|
+
|
|
71
|
+
// Summer should be UTC-4 (EDT), winter should be UTC-5 (EST)
|
|
72
|
+
expect(summerResult).not.toBe(winterResult);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe('getTimezoneAbbreviation', () => {
|
|
77
|
+
it('should get timezone abbreviation', () => {
|
|
78
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
79
|
+
const result = getTimezoneAbbreviation(date, 'America/New_York');
|
|
80
|
+
|
|
81
|
+
// Should return EST or EDT depending on DST
|
|
82
|
+
expect(result).toMatch(/EST|EDT|America\/New_York/);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should handle different timezones', () => {
|
|
86
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
87
|
+
const pst = getTimezoneAbbreviation(date, 'America/Los_Angeles');
|
|
88
|
+
const est = getTimezoneAbbreviation(date, 'America/New_York');
|
|
89
|
+
|
|
90
|
+
expect(pst).toBeTruthy();
|
|
91
|
+
expect(est).toBeTruthy();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should return timezone name on error', () => {
|
|
95
|
+
const date = new Date('invalid');
|
|
96
|
+
const result = getTimezoneAbbreviation(date, 'America/New_York');
|
|
97
|
+
expect(result).toBeTruthy();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should handle invalid timezone gracefully', () => {
|
|
101
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
102
|
+
const result = getTimezoneAbbreviation(date, '');
|
|
103
|
+
// Empty string returns 'UTC' as fallback per implementation
|
|
104
|
+
expect(result).toBe('UTC');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('formatTimeInTimeZone', () => {
|
|
109
|
+
it('should format time only in timezone', () => {
|
|
110
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
111
|
+
const result = formatTimeInTimeZone(date, 'America/New_York');
|
|
112
|
+
|
|
113
|
+
// Should be in HH:mm format
|
|
114
|
+
expect(result).toMatch(/^\d{2}:\d{2}$/);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should handle string date input', () => {
|
|
118
|
+
const result = formatTimeInTimeZone('2024-01-15T10:00:00Z', 'America/New_York');
|
|
119
|
+
expect(result).toMatch(/^\d{2}:\d{2}$/);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('getUserTimeZone', () => {
|
|
124
|
+
it('should return user timezone', () => {
|
|
125
|
+
const result = getUserTimeZone();
|
|
126
|
+
expect(typeof result).toBe('string');
|
|
127
|
+
expect(result.length).toBeGreaterThan(0);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should return UTC as fallback', () => {
|
|
131
|
+
// Mock Intl to be undefined
|
|
132
|
+
const originalIntl = global.Intl;
|
|
133
|
+
// @ts-expect-error - Testing error case
|
|
134
|
+
global.Intl = undefined;
|
|
135
|
+
|
|
136
|
+
const result = getUserTimeZone();
|
|
137
|
+
expect(result).toBe('UTC');
|
|
138
|
+
|
|
139
|
+
global.Intl = originalIntl;
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should handle Intl.DateTimeFormat errors gracefully', () => {
|
|
143
|
+
const originalIntl = global.Intl;
|
|
144
|
+
// @ts-expect-error - Testing error case
|
|
145
|
+
global.Intl = {
|
|
146
|
+
DateTimeFormat: () => {
|
|
147
|
+
throw new Error('Test error');
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const result = getUserTimeZone();
|
|
152
|
+
expect(result).toBe('UTC');
|
|
153
|
+
|
|
154
|
+
global.Intl = originalIntl;
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe('toZonedTime', () => {
|
|
159
|
+
it('should convert UTC to timezone local time', () => {
|
|
160
|
+
const utcDate = new Date('2024-01-15T10:00:00Z');
|
|
161
|
+
const result = toZonedTime(utcDate, 'America/New_York');
|
|
162
|
+
|
|
163
|
+
expect(result).toBeInstanceOf(Date);
|
|
164
|
+
expect(isNaN(result.getTime())).toBe(false);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should handle invalid date input', () => {
|
|
168
|
+
const result = toZonedTime(new Date('invalid'), 'America/New_York');
|
|
169
|
+
expect(isNaN(result.getTime())).toBe(true);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should handle invalid timezone', () => {
|
|
173
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
174
|
+
const result = toZonedTime(date, '');
|
|
175
|
+
// Empty timezone returns original date per implementation
|
|
176
|
+
expect(result).toBe(date);
|
|
177
|
+
expect(result.getTime()).toBe(date.getTime());
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should handle DST correctly', () => {
|
|
181
|
+
const summerDate = new Date('2024-07-15T10:00:00Z');
|
|
182
|
+
const winterDate = new Date('2024-01-15T10:00:00Z');
|
|
183
|
+
|
|
184
|
+
const summerResult = toZonedTime(summerDate, 'America/New_York');
|
|
185
|
+
const winterResult = toZonedTime(winterDate, 'America/New_York');
|
|
186
|
+
|
|
187
|
+
// Results should be different due to DST
|
|
188
|
+
expect(summerResult.getHours()).not.toBe(winterResult.getHours());
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('fromZonedTime', () => {
|
|
193
|
+
it('should convert local time to UTC', () => {
|
|
194
|
+
const localDate = new Date(2024, 0, 15, 10, 0); // Jan 15, 2024 10:00 AM (local)
|
|
195
|
+
const result = fromZonedTime(localDate, 'America/New_York');
|
|
196
|
+
|
|
197
|
+
expect(result).toBeInstanceOf(Date);
|
|
198
|
+
expect(isNaN(result.getTime())).toBe(false);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should handle invalid date input', () => {
|
|
202
|
+
const result = fromZonedTime(new Date('invalid'), 'America/New_York');
|
|
203
|
+
expect(isNaN(result.getTime())).toBe(true);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should handle invalid timezone', () => {
|
|
207
|
+
const date = new Date(2024, 0, 15, 10, 0);
|
|
208
|
+
const result = fromZonedTime(date, '');
|
|
209
|
+
// Empty timezone returns original date per implementation
|
|
210
|
+
expect(result).toBe(date);
|
|
211
|
+
expect(result.getTime()).toBe(date.getTime());
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('should correctly convert to UTC', () => {
|
|
215
|
+
// 10:00 AM EST (UTC-5) should be 15:00 UTC
|
|
216
|
+
// Using a specific date in January (no DST) for predictable results
|
|
217
|
+
const localDate = new Date(2024, 0, 15, 10, 0, 0, 0);
|
|
218
|
+
const utcResult = fromZonedTime(localDate, 'America/New_York');
|
|
219
|
+
|
|
220
|
+
// Check that it's approximately 5 hours ahead (EST is UTC-5)
|
|
221
|
+
// The actual difference depends on how fromZonedTime interprets the local date
|
|
222
|
+
// We just verify it's a valid date and the conversion happened
|
|
223
|
+
expect(isNaN(utcResult.getTime())).toBe(false);
|
|
224
|
+
expect(utcResult).toBeInstanceOf(Date);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
describe('roundToNearestMinutes', () => {
|
|
229
|
+
it('should round to nearest 5 minutes by default', () => {
|
|
230
|
+
const date = new Date('2024-01-15T10:23:00Z');
|
|
231
|
+
const result = roundToNearestMinutes(date);
|
|
232
|
+
|
|
233
|
+
expect(result).toBeInstanceOf(Date);
|
|
234
|
+
const minutes = result.getMinutes();
|
|
235
|
+
expect([0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55]).toContain(minutes);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should round to specified minutes step', () => {
|
|
239
|
+
const date = new Date('2024-01-15T10:23:00Z');
|
|
240
|
+
const result = roundToNearestMinutes(date, 15);
|
|
241
|
+
|
|
242
|
+
const minutes = result.getMinutes();
|
|
243
|
+
expect([0, 15, 30, 45]).toContain(minutes);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('should handle invalid date input', () => {
|
|
247
|
+
const result = roundToNearestMinutes(new Date('invalid'));
|
|
248
|
+
expect(isNaN(result.getTime())).toBe(true);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('should return original date for invalid minutesStep', () => {
|
|
252
|
+
const date = new Date('2024-01-15T10:23:00Z');
|
|
253
|
+
const result = roundToNearestMinutes(date, -5);
|
|
254
|
+
expect(result.getTime()).toBe(date.getTime());
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('should return original date for non-integer minutesStep', () => {
|
|
258
|
+
const date = new Date('2024-01-15T10:23:00Z');
|
|
259
|
+
const result = roundToNearestMinutes(date, 5.5);
|
|
260
|
+
expect(result.getTime()).toBe(date.getTime());
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('should round up correctly', () => {
|
|
264
|
+
const date = new Date('2024-01-15T10:23:00Z');
|
|
265
|
+
const result = roundToNearestMinutes(date, 5);
|
|
266
|
+
// Should round to 25 (closer to 25 than 20)
|
|
267
|
+
expect(result.getMinutes()).toBe(25);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
describe('getTimeZoneDifference', () => {
|
|
272
|
+
it('should calculate timezone difference in hours', () => {
|
|
273
|
+
const result = getTimeZoneDifference('America/New_York', 'America/Los_Angeles');
|
|
274
|
+
// EST is 3 hours ahead of PST
|
|
275
|
+
expect(result).toBe(-3);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('should handle UTC timezone', () => {
|
|
279
|
+
const result = getTimeZoneDifference('UTC', 'America/New_York');
|
|
280
|
+
// UTC to EST is -5 hours (or -4 during DST)
|
|
281
|
+
expect([-5, -4]).toContain(result);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it('should return 0 for same timezone', () => {
|
|
285
|
+
const result = getTimeZoneDifference('America/New_York', 'America/New_York');
|
|
286
|
+
expect(result).toBe(0);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('should handle invalid timezones gracefully', () => {
|
|
290
|
+
const result = getTimeZoneDifference('', 'America/New_York');
|
|
291
|
+
expect(result).toBe(0);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it('should handle reversed timezones', () => {
|
|
295
|
+
const forward = getTimeZoneDifference('America/New_York', 'America/Los_Angeles');
|
|
296
|
+
const backward = getTimeZoneDifference('America/Los_Angeles', 'America/New_York');
|
|
297
|
+
|
|
298
|
+
expect(forward).toBe(-backward);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('should account for DST in calculations', () => {
|
|
302
|
+
// Test with a summer date (DST active)
|
|
303
|
+
const summerDiff = getTimeZoneDifference('UTC', 'America/New_York');
|
|
304
|
+
// Should be -4 (EDT) or -5 (EST) depending on current date
|
|
305
|
+
expect([-4, -5]).toContain(summerDiff);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
describe('Edge cases and error handling', () => {
|
|
310
|
+
it('should handle null and undefined gracefully', () => {
|
|
311
|
+
// @ts-expect-error - Testing error case
|
|
312
|
+
expect(formatInTimeZone(null, 'America/New_York', 'MMM dd, yyyy')).toBe('Invalid date');
|
|
313
|
+
// @ts-expect-error - Testing error case
|
|
314
|
+
expect(formatInTimeZone(undefined, 'America/New_York', 'MMM dd, yyyy')).toBe('Invalid date');
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('should handle various timezone formats', () => {
|
|
318
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
319
|
+
const timezones = [
|
|
320
|
+
'America/New_York',
|
|
321
|
+
'Europe/London',
|
|
322
|
+
'Asia/Tokyo',
|
|
323
|
+
'Australia/Sydney',
|
|
324
|
+
'UTC'
|
|
325
|
+
];
|
|
326
|
+
|
|
327
|
+
timezones.forEach(tz => {
|
|
328
|
+
const result = formatInTimeZone(date, tz, 'MMM dd, yyyy');
|
|
329
|
+
expect(result).not.toBe('Invalid date');
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it('should handle extreme dates', () => {
|
|
334
|
+
const farFuture = new Date('2099-12-31T23:59:59Z');
|
|
335
|
+
// Use a date that won't have timezone boundary issues
|
|
336
|
+
const farPast = new Date('1900-01-01T12:00:00Z');
|
|
337
|
+
|
|
338
|
+
expect(formatInTimeZone(farFuture, 'America/New_York', 'yyyy')).toContain('2099');
|
|
339
|
+
// The year might be 1899 or 1900 depending on timezone conversion, so just check it's valid
|
|
340
|
+
const pastResult = formatInTimeZone(farPast, 'America/New_York', 'yyyy');
|
|
341
|
+
expect(pastResult).not.toBe('Invalid date');
|
|
342
|
+
expect(pastResult.length).toBeGreaterThan(0);
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
});
|
|
@@ -50,6 +50,7 @@ const mockFileUploadOptions = {
|
|
|
50
50
|
organisation_id: 'test-org-123',
|
|
51
51
|
app_id: 'test-app-123',
|
|
52
52
|
category: FileCategory.GENERAL_DOCUMENTS,
|
|
53
|
+
pageContext: 'configuration',
|
|
53
54
|
is_public: false
|
|
54
55
|
};
|
|
55
56
|
|
|
@@ -116,6 +117,7 @@ describe('[service] FileReferenceServiceImpl', () => {
|
|
|
116
117
|
p_record_id: mockFileUploadOptions.record_id,
|
|
117
118
|
p_organisation_id: mockFileUploadOptions.organisation_id,
|
|
118
119
|
p_app_id: mockFileUploadOptions.app_id,
|
|
120
|
+
p_page_context: mockFileUploadOptions.pageContext,
|
|
119
121
|
p_file_metadata: expect.objectContaining({
|
|
120
122
|
fileName: testFile.name,
|
|
121
123
|
fileType: testFile.type,
|
|
@@ -88,6 +88,7 @@ export class FileReferenceServiceImpl implements FileReferenceService {
|
|
|
88
88
|
p_file_path: filePath, // Storage path from step 1
|
|
89
89
|
p_organisation_id: options.organisation_id,
|
|
90
90
|
p_app_id: options.app_id,
|
|
91
|
+
p_page_context: options.pageContext,
|
|
91
92
|
p_file_metadata: {
|
|
92
93
|
fileName: file.name,
|
|
93
94
|
fileType: file.type,
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Timezone-Aware Date Formatting Tests
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Utils/Formatting/__tests__
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* Comprehensive tests for timezone-aware date formatting functions.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, it, expect } from 'vitest';
|
|
11
|
+
import {
|
|
12
|
+
formatDateTimeForDisplay,
|
|
13
|
+
formatDateOnlyForDisplay,
|
|
14
|
+
formatDateTimeForTable,
|
|
15
|
+
formatDateTimeForMap,
|
|
16
|
+
type DateTimeFormatOptions
|
|
17
|
+
} from './formatting';
|
|
18
|
+
|
|
19
|
+
describe('Timezone-Aware Date Formatting', () => {
|
|
20
|
+
describe('formatDateTimeForDisplay', () => {
|
|
21
|
+
it('formats UTC date with timezone abbreviation', () => {
|
|
22
|
+
const result = formatDateTimeForDisplay('2024-01-15T10:00:00Z', 'America/New_York');
|
|
23
|
+
expect(result).toMatch(/Jan 15, 2024/);
|
|
24
|
+
expect(result).toMatch(/\(/); // Should include timezone abbreviation in parentheses
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('formats Date object with timezone', () => {
|
|
28
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
29
|
+
const result = formatDateTimeForDisplay(date, 'America/New_York');
|
|
30
|
+
expect(result).toMatch(/Jan 15, 2024/);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('excludes timezone when includeTimezone is false', () => {
|
|
34
|
+
const options: DateTimeFormatOptions = { includeTimezone: false };
|
|
35
|
+
const result = formatDateTimeForDisplay('2024-01-15T10:00:00Z', 'America/New_York', options);
|
|
36
|
+
expect(result).toMatch(/Jan 15, 2024/);
|
|
37
|
+
expect(result).not.toMatch(/\(/); // Should not include parentheses
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('uses custom format string', () => {
|
|
41
|
+
const options: DateTimeFormatOptions = { format: 'yyyy-MM-dd HH:mm' };
|
|
42
|
+
const result = formatDateTimeForDisplay('2024-01-15T10:00:00Z', 'America/New_York', options);
|
|
43
|
+
expect(result).toMatch(/2024-01-15/);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('returns empty string for undefined date', () => {
|
|
47
|
+
const result = formatDateTimeForDisplay(undefined, 'America/New_York');
|
|
48
|
+
expect(result).toBe('');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('returns empty string for undefined timezone', () => {
|
|
52
|
+
const result = formatDateTimeForDisplay('2024-01-15T10:00:00Z', undefined);
|
|
53
|
+
expect(result).toBe('');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('returns empty string for invalid date', () => {
|
|
57
|
+
const result = formatDateTimeForDisplay('invalid-date', 'America/New_York');
|
|
58
|
+
expect(result).toBe('');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('handles different timezones correctly', () => {
|
|
62
|
+
const date = '2024-01-15T10:00:00Z';
|
|
63
|
+
const ny = formatDateTimeForDisplay(date, 'America/New_York');
|
|
64
|
+
const la = formatDateTimeForDisplay(date, 'America/Los_Angeles');
|
|
65
|
+
expect(ny).not.toBe(la);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('formatDateOnlyForDisplay', () => {
|
|
70
|
+
it('formats date only without time', () => {
|
|
71
|
+
const result = formatDateOnlyForDisplay('2024-01-15T10:00:00Z');
|
|
72
|
+
expect(result).toMatch(/January/);
|
|
73
|
+
expect(result).toMatch(/2024/);
|
|
74
|
+
expect(result).toMatch(/15/);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('formats Date object', () => {
|
|
78
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
79
|
+
const result = formatDateOnlyForDisplay(date);
|
|
80
|
+
expect(result).toMatch(/January/);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('returns empty string for undefined', () => {
|
|
84
|
+
const result = formatDateOnlyForDisplay(undefined);
|
|
85
|
+
expect(result).toBe('');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('returns empty string for invalid date', () => {
|
|
89
|
+
const result = formatDateOnlyForDisplay('invalid-date');
|
|
90
|
+
expect(result).toBe('');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('formats different dates correctly', () => {
|
|
94
|
+
const dates = [
|
|
95
|
+
'2024-01-15T10:00:00Z',
|
|
96
|
+
'2024-06-15T12:00:00Z',
|
|
97
|
+
'2024-12-31T23:59:59Z'
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
dates.forEach(date => {
|
|
101
|
+
const result = formatDateOnlyForDisplay(date);
|
|
102
|
+
expect(result).toBeTruthy();
|
|
103
|
+
expect(result.length).toBeGreaterThan(0);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('formatDateTimeForTable', () => {
|
|
109
|
+
it('formats date for table display with timezone', () => {
|
|
110
|
+
const result = formatDateTimeForTable('2024-01-15T10:00:00Z', 'America/New_York');
|
|
111
|
+
expect(result).toMatch(/Jan 15, 2024/);
|
|
112
|
+
expect(result).toMatch(/\(/); // Should include timezone
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('returns empty string for undefined date', () => {
|
|
116
|
+
const result = formatDateTimeForTable(undefined, 'America/New_York');
|
|
117
|
+
expect(result).toBe('');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('returns empty string for undefined timezone', () => {
|
|
121
|
+
const result = formatDateTimeForTable('2024-01-15T10:00:00Z', undefined);
|
|
122
|
+
expect(result).toBe('');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('formats Date object', () => {
|
|
126
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
127
|
+
const result = formatDateTimeForTable(date, 'America/New_York');
|
|
128
|
+
expect(result).toMatch(/Jan 15, 2024/);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe('formatDateTimeForMap', () => {
|
|
133
|
+
it('formats date for map display', () => {
|
|
134
|
+
const result = formatDateTimeForMap('2024-01-15T10:00:00Z', 'America/New_York');
|
|
135
|
+
expect(result).toMatch(/Jan 15/);
|
|
136
|
+
expect(result).toMatch(/\d{2}:\d{2}/); // Time format
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('includes timezone abbreviation', () => {
|
|
140
|
+
const result = formatDateTimeForMap('2024-01-15T10:00:00Z', 'America/New_York');
|
|
141
|
+
expect(result.length).toBeGreaterThan(0);
|
|
142
|
+
// Should include timezone info (not in parentheses for map format)
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('returns empty string for undefined date', () => {
|
|
146
|
+
const result = formatDateTimeForMap(undefined, 'America/New_York');
|
|
147
|
+
expect(result).toBe('');
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('returns empty string for undefined timezone', () => {
|
|
151
|
+
const result = formatDateTimeForMap('2024-01-15T10:00:00Z', undefined);
|
|
152
|
+
expect(result).toBe('');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('formats Date object', () => {
|
|
156
|
+
const date = new Date('2024-01-15T10:00:00Z');
|
|
157
|
+
const result = formatDateTimeForMap(date, 'America/New_York');
|
|
158
|
+
expect(result).toMatch(/Jan 15/);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('returns empty string for invalid date', () => {
|
|
162
|
+
const result = formatDateTimeForMap('invalid-date', 'America/New_York');
|
|
163
|
+
expect(result).toBe('');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|