@oneuptime/common 12.0.13 → 12.0.14
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/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
- package/Models/DatabaseModels/UserCall.ts +94 -3
- package/Models/DatabaseModels/UserEmail.ts +94 -3
- package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
- package/Models/DatabaseModels/UserPush.ts +37 -0
- package/Models/DatabaseModels/UserSMS.ts +94 -3
- package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
- package/Server/API/BaseAPI.ts +79 -14
- package/Server/API/UserCallAPI.ts +53 -45
- package/Server/API/UserEmailAPI.ts +53 -44
- package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
- package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
- package/Server/API/UserPushAPI.ts +126 -2
- package/Server/API/UserSmsAPI.ts +53 -44
- package/Server/API/UserWhatsAppAPI.ts +53 -50
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
- package/Server/Services/AnalyticsDatabaseService.ts +169 -0
- package/Server/Services/DatabaseService.ts +101 -0
- package/Server/Services/LogAggregationService.ts +5 -0
- package/Server/Services/PushNotificationService.ts +127 -12
- package/Server/Services/TeamMemberService.ts +53 -13
- package/Server/Services/UserCallService.ts +55 -24
- package/Server/Services/UserEmailService.ts +83 -17
- package/Server/Services/UserIncomingCallNumberService.ts +49 -85
- package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
- package/Server/Services/UserNotificationRuleService.ts +26 -0
- package/Server/Services/UserPushService.ts +89 -0
- package/Server/Services/UserSmsService.ts +50 -17
- package/Server/Services/UserWhatsAppService.ts +48 -15
- package/Server/Types/Database/QueryHelper.ts +30 -0
- package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
- package/Server/Utils/ChannelVerification.ts +510 -0
- package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +13 -16
- package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
- package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
- package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
- package/Server/Utils/TotpAuth.ts +137 -9
- package/Server/Utils/UserRegistrationToken.ts +182 -0
- package/Server/Utils/VerificationCode.ts +134 -0
- package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
- package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
- package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +28 -0
- package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
- package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
- package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
- package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
- package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
- package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
- package/Tests/Server/API/UserSmsApi.test.ts +107 -14
- package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
- package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +315 -0
- package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
- package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +10 -62
- package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
- package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
- package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
- package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
- package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
- package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
- package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
- package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
- package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
- package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
- package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
- package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
- package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
- package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
- package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
- package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
- package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
- package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
- package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
- package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
- package/Tests/Server/Utils/Browser.test.ts +162 -0
- package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
- package/Tests/Server/Utils/Express.test.ts +371 -0
- package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
- package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
- package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
- package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
- package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
- package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
- package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
- package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
- package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
- package/Tests/Types/Call/CallRequest.test.ts +189 -0
- package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
- package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
- package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
- package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
- package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
- package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
- package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
- package/Tests/Types/TextRandomGeneration.test.ts +211 -0
- package/Tests/UI/Components/Button.test.tsx +175 -1
- package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
- package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
- package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
- package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
- package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
- package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
- package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
- package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
- package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
- package/Tests/UI/Components/List.test.tsx +9 -2
- package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
- package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
- package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
- package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
- package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
- package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
- package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
- package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
- package/Tests/UI/Components/Skeleton.test.tsx +71 -0
- package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
- package/Tests/UI/Components/Tabs.test.tsx +24 -0
- package/Tests/UI/Components/Toast.test.tsx +130 -7
- package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
- package/Tests/UI/Utils/Dropdown.test.ts +423 -0
- package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
- package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
- package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
- package/Tests/Utils/API.test.ts +16 -2
- package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
- package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
- package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
- package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
- package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
- package/Types/Permission.ts +35 -0
- package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
- package/Types/PushNotification/PushNotificationMessage.ts +15 -0
- package/Types/PushNotification/PushNotificationRequest.ts +8 -16
- package/Types/Service/ServiceLanguage.ts +144 -0
- package/Types/Text.ts +111 -19
- package/UI/Components/Button/Button.tsx +27 -14
- package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
- package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
- package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
- package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
- package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
- package/UI/Components/CommandPalette/Types.ts +49 -0
- package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
- package/UI/Components/Dropdown/Dropdown.tsx +6 -1
- package/UI/Components/Feed/FeedItem.tsx +1 -1
- package/UI/Components/List/List.tsx +37 -5
- package/UI/Components/List/ListSkeleton.tsx +54 -0
- package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +6 -1
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
- package/UI/Components/Modal/Modal.tsx +2 -2
- package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
- package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
- package/UI/Components/Navbar/NavBar.tsx +14 -1
- package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
- package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
- package/UI/Components/SideOver/SideOver.tsx +37 -2
- package/UI/Components/Skeleton/Skeleton.tsx +53 -0
- package/UI/Components/Table/Table.tsx +74 -44
- package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
- package/UI/Components/Tabs/Tab.tsx +1 -1
- package/UI/Components/Toast/Toast.tsx +118 -53
- package/UI/Components/Toast/ToastInit.tsx +82 -32
- package/UI/Styles/Theme.css +40 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
- package/UI/Utils/ModelListCache.ts +188 -0
- package/UI/Utils/Project.ts +29 -0
- package/Utils/API.ts +6 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
- package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
- package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
- package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
- package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +69 -13
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/UserCallAPI.js +42 -38
- package/build/dist/Server/API/UserCallAPI.js.map +1 -1
- package/build/dist/Server/API/UserEmailAPI.js +42 -38
- package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
- package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
- package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
- package/build/dist/Server/API/UserPushAPI.js +95 -2
- package/build/dist/Server/API/UserPushAPI.js.map +1 -1
- package/build/dist/Server/API/UserSmsAPI.js +42 -38
- package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
- package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
- package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
- package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +74 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +5 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/PushNotificationService.js +69 -30
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +43 -7
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/UserCallService.js +54 -22
- package/build/dist/Server/Services/UserCallService.js.map +1 -1
- package/build/dist/Server/Services/UserEmailService.js +78 -17
- package/build/dist/Server/Services/UserEmailService.js.map +1 -1
- package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
- package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
- package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserPushService.js +77 -0
- package/build/dist/Server/Services/UserPushService.js.map +1 -1
- package/build/dist/Server/Services/UserSmsService.js +50 -17
- package/build/dist/Server/Services/UserSmsService.js.map +1 -1
- package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
- package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
- package/build/dist/Server/Utils/ChannelVerification.js +348 -0
- package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +13 -12
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/TotpAuth.js +127 -8
- package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
- package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
- package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
- package/build/dist/Server/Utils/VerificationCode.js +120 -0
- package/build/dist/Server/Utils/VerificationCode.js.map +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
- package/build/dist/Types/Permission.js +33 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
- package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
- package/build/dist/Types/Service/ServiceLanguage.js +96 -0
- package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
- package/build/dist/Types/Text.js +82 -17
- package/build/dist/Types/Text.js.map +1 -1
- package/build/dist/UI/Components/Button/Button.js +22 -14
- package/build/dist/UI/Components/Button/Button.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
- package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
- package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
- package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
- package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
- package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
- package/build/dist/UI/Components/List/List.js +19 -5
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
- package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +2 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
- package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
- package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +35 -24
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
- package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
- package/build/dist/UI/Components/Tabs/Tab.js +1 -1
- package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
- package/build/dist/UI/Components/Toast/Toast.js +77 -23
- package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
- package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
- package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/ModelListCache.js +126 -0
- package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
- package/build/dist/UI/Utils/Project.js +24 -1
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/build/dist/Utils/API.js +6 -1
- package/build/dist/Utils/API.js.map +1 -1
- package/jest.config.json +1 -1
- package/package.json +2 -3
- package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
- package/Tests/__mocks__/otpauth.js +0 -30
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import {
|
|
2
|
+
afterEach,
|
|
3
|
+
beforeEach,
|
|
4
|
+
describe,
|
|
5
|
+
expect,
|
|
6
|
+
jest,
|
|
7
|
+
test,
|
|
8
|
+
} from "@jest/globals";
|
|
9
|
+
import "@testing-library/jest-dom";
|
|
10
|
+
import {
|
|
11
|
+
act,
|
|
12
|
+
cleanup,
|
|
13
|
+
fireEvent,
|
|
14
|
+
render,
|
|
15
|
+
screen,
|
|
16
|
+
} from "@testing-library/react";
|
|
17
|
+
import * as React from "react";
|
|
18
|
+
import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
* The flagship interaction of the command palette — press Cmd/Ctrl+K anywhere
|
|
22
|
+
* on the dashboard and the palette appears — lives entirely in the
|
|
23
|
+
* DashboardCommandPalette host: a document-level keydown listener plus a
|
|
24
|
+
* GlobalEvents subscription. The App suite runs in plain node and can only
|
|
25
|
+
* pin source patterns, so this suite actually mounts the host (real
|
|
26
|
+
* CommandPalette underneath, portal and all) and fires the real events.
|
|
27
|
+
*
|
|
28
|
+
* Escape/close-key semantics inside the open palette are deliberately NOT
|
|
29
|
+
* pinned here — they belong to the Common CommandPalette's own contract. This
|
|
30
|
+
* suite owns only the host's chord, its politeness rules, the global toggle
|
|
31
|
+
* event, and listener cleanup.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const navigateMock: MockFunction = getJestMockFunction();
|
|
35
|
+
const getListMock: MockFunction = getJestMockFunction();
|
|
36
|
+
const getCurrentProjectIdMock: MockFunction = getJestMockFunction();
|
|
37
|
+
const getAllPermissionsMock: MockFunction = getJestMockFunction();
|
|
38
|
+
const isMasterAdminMock: MockFunction = getJestMockFunction();
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
* The arrow wrappers are load bearing: jest.mock is hoisted above the
|
|
42
|
+
* compiled requires, so the consts above are still in their temporal dead
|
|
43
|
+
* zone when the factory body runs. Dereferencing them lazily, at call time,
|
|
44
|
+
* is what works (same pattern as InvestigationPanel.test.tsx).
|
|
45
|
+
*/
|
|
46
|
+
jest.mock("react-i18next", () => {
|
|
47
|
+
return {
|
|
48
|
+
useTranslation: () => {
|
|
49
|
+
return {
|
|
50
|
+
t: (key: string, defaultValue?: string): string => {
|
|
51
|
+
return defaultValue ?? key;
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
|
|
59
|
+
return {
|
|
60
|
+
__esModule: true,
|
|
61
|
+
default: {
|
|
62
|
+
getList: (...args: Array<unknown>) => {
|
|
63
|
+
return getListMock(...args);
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
jest.mock("../../../UI/Utils/Navigation", () => {
|
|
70
|
+
return {
|
|
71
|
+
__esModule: true,
|
|
72
|
+
default: {
|
|
73
|
+
navigate: (...args: Array<unknown>) => {
|
|
74
|
+
return navigateMock(...args);
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
jest.mock("../../../UI/Utils/Permission", () => {
|
|
81
|
+
return {
|
|
82
|
+
__esModule: true,
|
|
83
|
+
default: {
|
|
84
|
+
getAllPermissions: (...args: Array<unknown>) => {
|
|
85
|
+
return getAllPermissionsMock(...args);
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
jest.mock("../../../UI/Utils/User", () => {
|
|
92
|
+
return {
|
|
93
|
+
__esModule: true,
|
|
94
|
+
default: {
|
|
95
|
+
isMasterAdmin: (...args: Array<unknown>) => {
|
|
96
|
+
return isMasterAdminMock(...args);
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
jest.mock("../../../UI/Utils/Project", () => {
|
|
103
|
+
return {
|
|
104
|
+
__esModule: true,
|
|
105
|
+
default: {
|
|
106
|
+
getCurrentProjectId: (...args: Array<unknown>) => {
|
|
107
|
+
return getCurrentProjectIdMock(...args);
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
/*
|
|
114
|
+
* The real catalog hook walks the full RouteMap through useTranslation; the
|
|
115
|
+
* host only needs SOME catalog, so a single-page one keeps the suite about
|
|
116
|
+
* the host's event wiring rather than the NavBar's contents.
|
|
117
|
+
*/
|
|
118
|
+
jest.mock(
|
|
119
|
+
"../../../../App/FeatureSet/Dashboard/src/Utils/NavigationItems",
|
|
120
|
+
() => {
|
|
121
|
+
const useDashboardNavigationItemsStub: () => unknown = (): unknown => {
|
|
122
|
+
/*
|
|
123
|
+
* Route is loaded lazily for the same hoisting reason as the mock
|
|
124
|
+
* functions above; requireActual keeps it the real class.
|
|
125
|
+
*/
|
|
126
|
+
const RouteClass: typeof import("../../../Types/API/Route").default = (
|
|
127
|
+
jest.requireActual("../../../Types/API/Route") as {
|
|
128
|
+
default: typeof import("../../../Types/API/Route").default;
|
|
129
|
+
}
|
|
130
|
+
).default;
|
|
131
|
+
return {
|
|
132
|
+
navItems: [
|
|
133
|
+
{
|
|
134
|
+
id: "home-nav-bar-item",
|
|
135
|
+
title: "Home",
|
|
136
|
+
icon: "Home",
|
|
137
|
+
route: new RouteClass("/dashboard/abc123/home"),
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
moreMenuItems: [],
|
|
141
|
+
rightElement: {
|
|
142
|
+
id: "user-profile-nav-bar-item",
|
|
143
|
+
title: "User Profile",
|
|
144
|
+
description: "Your account",
|
|
145
|
+
icon: "User",
|
|
146
|
+
route: new RouteClass("/dashboard/user-profile/picture"),
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// The App source consumes the hook as the module's default export.
|
|
152
|
+
return {
|
|
153
|
+
__esModule: true,
|
|
154
|
+
default: useDashboardNavigationItemsStub,
|
|
155
|
+
useDashboardNavigationItems: useDashboardNavigationItemsStub,
|
|
156
|
+
};
|
|
157
|
+
},
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
import DashboardCommandPalette from "../../../../App/FeatureSet/Dashboard/src/Components/CommandPalette/DashboardCommandPalette";
|
|
161
|
+
import EventName from "../../../../App/FeatureSet/Dashboard/src/Utils/EventName";
|
|
162
|
+
import GlobalEvents from "../../../UI/Utils/GlobalEvents";
|
|
163
|
+
|
|
164
|
+
function palette(): HTMLElement | null {
|
|
165
|
+
return screen.queryByTestId("command-palette");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/*
|
|
169
|
+
* The chord is dispatched on document.body — where real key events land when
|
|
170
|
+
* no input is focused — and bubbles up to the host's document-level listener.
|
|
171
|
+
*/
|
|
172
|
+
function pressChord(init: KeyboardEventInit): void {
|
|
173
|
+
fireEvent.keyDown(document.body, init);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
beforeEach(() => {
|
|
177
|
+
/*
|
|
178
|
+
* The open panel schedules an enter-transition frame (rAF + fallback
|
|
179
|
+
* timer); fake timers keep those under act()'s control.
|
|
180
|
+
*/
|
|
181
|
+
jest.useFakeTimers();
|
|
182
|
+
getCurrentProjectIdMock.mockReturnValue(null);
|
|
183
|
+
getAllPermissionsMock.mockReturnValue([]);
|
|
184
|
+
isMasterAdminMock.mockReturnValue(false);
|
|
185
|
+
getListMock.mockResolvedValue({ data: [], count: 0 } as never);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
afterEach(() => {
|
|
189
|
+
cleanup();
|
|
190
|
+
jest.clearAllTimers();
|
|
191
|
+
jest.useRealTimers();
|
|
192
|
+
navigateMock.mockReset();
|
|
193
|
+
getListMock.mockReset();
|
|
194
|
+
getCurrentProjectIdMock.mockReset();
|
|
195
|
+
getAllPermissionsMock.mockReset();
|
|
196
|
+
isMasterAdminMock.mockReset();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe("DashboardCommandPalette Cmd/Ctrl+K chord", () => {
|
|
200
|
+
test("Cmd+K on the document opens the palette", () => {
|
|
201
|
+
render(<DashboardCommandPalette />);
|
|
202
|
+
expect(palette()).toBeNull();
|
|
203
|
+
|
|
204
|
+
pressChord({ key: "k", metaKey: true });
|
|
205
|
+
|
|
206
|
+
expect(palette()).toBeInTheDocument();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test("the same chord closes an open palette", () => {
|
|
210
|
+
render(<DashboardCommandPalette />);
|
|
211
|
+
|
|
212
|
+
pressChord({ key: "k", metaKey: true });
|
|
213
|
+
expect(palette()).toBeInTheDocument();
|
|
214
|
+
|
|
215
|
+
pressChord({ key: "k", metaKey: true });
|
|
216
|
+
expect(palette()).toBeNull();
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
test("Ctrl+K works exactly like Cmd+K (Windows/Linux)", () => {
|
|
220
|
+
render(<DashboardCommandPalette />);
|
|
221
|
+
|
|
222
|
+
pressChord({ key: "k", ctrlKey: true });
|
|
223
|
+
expect(palette()).toBeInTheDocument();
|
|
224
|
+
|
|
225
|
+
pressChord({ key: "k", ctrlKey: true });
|
|
226
|
+
expect(palette()).toBeNull();
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test("a chord another handler already claimed (defaultPrevented) is ignored", () => {
|
|
230
|
+
render(<DashboardCommandPalette />);
|
|
231
|
+
|
|
232
|
+
/*
|
|
233
|
+
* A capture-phase window listener models "some earlier handler took this
|
|
234
|
+
* chord": it runs before the host's document listener and claims the
|
|
235
|
+
* event, exactly the situation defaultPrevented is checked for.
|
|
236
|
+
*/
|
|
237
|
+
const claimChord: (event: KeyboardEvent) => void = (
|
|
238
|
+
event: KeyboardEvent,
|
|
239
|
+
): void => {
|
|
240
|
+
event.preventDefault();
|
|
241
|
+
};
|
|
242
|
+
window.addEventListener("keydown", claimChord, { capture: true });
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
pressChord({ key: "k", metaKey: true });
|
|
246
|
+
expect(palette()).toBeNull();
|
|
247
|
+
} finally {
|
|
248
|
+
window.removeEventListener("keydown", claimChord, { capture: true });
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// And with the claimer gone the same chord opens the palette again.
|
|
252
|
+
pressChord({ key: "k", metaKey: true });
|
|
253
|
+
expect(palette()).toBeInTheDocument();
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
test("extra modifiers on the chord do not open the palette", () => {
|
|
257
|
+
render(<DashboardCommandPalette />);
|
|
258
|
+
|
|
259
|
+
pressChord({ key: "k", metaKey: true, shiftKey: true });
|
|
260
|
+
pressChord({ key: "k", ctrlKey: true, altKey: true });
|
|
261
|
+
pressChord({ key: "k" });
|
|
262
|
+
|
|
263
|
+
expect(palette()).toBeNull();
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
describe("DashboardCommandPalette global toggle event", () => {
|
|
268
|
+
test("the COMMAND_PALETTE_TOGGLE event toggles the palette", () => {
|
|
269
|
+
render(<DashboardCommandPalette />);
|
|
270
|
+
expect(palette()).toBeNull();
|
|
271
|
+
|
|
272
|
+
act((): void => {
|
|
273
|
+
GlobalEvents.dispatchEvent(EventName.COMMAND_PALETTE_TOGGLE);
|
|
274
|
+
});
|
|
275
|
+
expect(palette()).toBeInTheDocument();
|
|
276
|
+
|
|
277
|
+
act((): void => {
|
|
278
|
+
GlobalEvents.dispatchEvent(EventName.COMMAND_PALETTE_TOGGLE);
|
|
279
|
+
});
|
|
280
|
+
expect(palette()).toBeNull();
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
describe("DashboardCommandPalette listener cleanup", () => {
|
|
285
|
+
test("unmounting removes every document keydown listener it added, same references", () => {
|
|
286
|
+
const addSpy: ReturnType<typeof jest.spyOn> = jest.spyOn(
|
|
287
|
+
document,
|
|
288
|
+
"addEventListener",
|
|
289
|
+
);
|
|
290
|
+
const removeSpy: ReturnType<typeof jest.spyOn> = jest.spyOn(
|
|
291
|
+
document,
|
|
292
|
+
"removeEventListener",
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
const view: ReturnType<typeof render> = render(
|
|
297
|
+
<DashboardCommandPalette />,
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
const addedKeydownListeners: Array<unknown> = addSpy.mock.calls
|
|
301
|
+
.filter((call: Array<unknown>): boolean => {
|
|
302
|
+
return call[0] === "keydown";
|
|
303
|
+
})
|
|
304
|
+
.map((call: Array<unknown>): unknown => {
|
|
305
|
+
return call[1];
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// The host claims the chord at the document level while mounted.
|
|
309
|
+
expect(addedKeydownListeners.length).toBeGreaterThanOrEqual(1);
|
|
310
|
+
|
|
311
|
+
view.unmount();
|
|
312
|
+
|
|
313
|
+
const removedKeydownListeners: Array<unknown> = removeSpy.mock.calls
|
|
314
|
+
.filter((call: Array<unknown>): boolean => {
|
|
315
|
+
return call[0] === "keydown";
|
|
316
|
+
})
|
|
317
|
+
.map((call: Array<unknown>): unknown => {
|
|
318
|
+
return call[1];
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
/*
|
|
322
|
+
* Every added listener must be removed with the SAME function
|
|
323
|
+
* reference — an inline re-created arrow in the cleanup would leave
|
|
324
|
+
* the original behind and stack a listener per mount.
|
|
325
|
+
*/
|
|
326
|
+
for (const listener of addedKeydownListeners) {
|
|
327
|
+
expect(removedKeydownListeners).toContain(listener);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// And a chord after unmount reaches nothing.
|
|
331
|
+
pressChord({ key: "k", metaKey: true });
|
|
332
|
+
expect(palette()).toBeNull();
|
|
333
|
+
} finally {
|
|
334
|
+
addSpy.mockRestore();
|
|
335
|
+
removeSpy.mockRestore();
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
});
|
|
@@ -60,7 +60,7 @@ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
|
|
|
60
60
|
* Record MarkdownViewer's props so safeMode remains an asserted part of the
|
|
61
61
|
* contract even when the Common Jest config replaces its markdown renderer.
|
|
62
62
|
*/
|
|
63
|
-
jest.mock("../../../UI/Components/Markdown.tsx/
|
|
63
|
+
jest.mock("../../../UI/Components/Markdown.tsx/LazyMarkdownViewer", () => {
|
|
64
64
|
return {
|
|
65
65
|
__esModule: true,
|
|
66
66
|
default: (props: MarkdownViewerProps): React.ReactElement => {
|
|
@@ -51,6 +51,15 @@ const search: SearchFunction = (value: string): void => {
|
|
|
51
51
|
});
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
+
// Every type the catalog actually offers, in the order the picker lists them.
|
|
55
|
+
const catalogTypeValues: Array<string> = categorizedOptions.flatMap(
|
|
56
|
+
(group: CardSelectOptionGroup) => {
|
|
57
|
+
return group.options.map((option: CardSelectOption) => {
|
|
58
|
+
return option.value;
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
|
|
54
63
|
type ShownTypesFunction = () => Array<string>;
|
|
55
64
|
|
|
56
65
|
const shownTypes: ShownTypesFunction = (): Array<string> => {
|
|
@@ -231,6 +240,25 @@ describe("Monitor type picker", () => {
|
|
|
231
240
|
|
|
232
241
|
expect(onChange).toHaveBeenCalledWith(MonitorType.Kubernetes);
|
|
233
242
|
});
|
|
243
|
+
|
|
244
|
+
/*
|
|
245
|
+
* The e2e suite reaches a folded-away type by typing its MonitorType value
|
|
246
|
+
* into this box and then clicking card-select-option-<value>
|
|
247
|
+
* (selectMonitorTypeCard in E2E/Tests/Dashboard/Helpers/Monitors.ts). That
|
|
248
|
+
* only holds while every type's own value is a search term that finds it,
|
|
249
|
+
* which a renamed title or a reworded description can quietly break — and
|
|
250
|
+
* the only thing that would notice is a full release e2e run.
|
|
251
|
+
*/
|
|
252
|
+
test.each(catalogTypeValues)(
|
|
253
|
+
"typing %s finds the card the e2e suite goes on to click",
|
|
254
|
+
(value: string) => {
|
|
255
|
+
renderPicker();
|
|
256
|
+
|
|
257
|
+
search(value);
|
|
258
|
+
|
|
259
|
+
expect(screen.getByTestId(`card-select-option-${value}`)).toBeVisible();
|
|
260
|
+
},
|
|
261
|
+
);
|
|
234
262
|
});
|
|
235
263
|
|
|
236
264
|
describe("coming back to a form that already has a type", () => {
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UserPush.isCriticalAlertEnabled column contract.
|
|
3
|
+
*
|
|
4
|
+
* This is the one stored preference in the product whose purpose is to DEFEAT
|
|
5
|
+
* a choice the user made with a physical switch on their phone. Everything
|
|
6
|
+
* below pins a property that, quietly changed, either wakes people who did not
|
|
7
|
+
* ask to be woken or - far worse for an on-call product - stops waking people
|
|
8
|
+
* who did.
|
|
9
|
+
*
|
|
10
|
+
* The three "default" mechanisms are separate and easy to confuse:
|
|
11
|
+
* - NEW rows get false from the Postgres column default (@Column default)
|
|
12
|
+
* - EXISTING rows got false from the migration's NOT NULL DEFAULT false
|
|
13
|
+
* - @TableColumn defaultValue is documentation for the generated API schema
|
|
14
|
+
* and forms; it defaults nothing at runtime
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import UserPush from "../../Models/DatabaseModels/UserPush";
|
|
18
|
+
import { TableColumnMetadata } from "../../Types/Database/TableColumn";
|
|
19
|
+
import TableColumnType from "../../Types/Database/TableColumnType";
|
|
20
|
+
import Permission from "../../Types/Permission";
|
|
21
|
+
import { describe, expect, test } from "@jest/globals";
|
|
22
|
+
import { getMetadataArgsStorage } from "typeorm";
|
|
23
|
+
import { ColumnMetadataArgs } from "typeorm/metadata-args/ColumnMetadataArgs";
|
|
24
|
+
import fs from "fs";
|
|
25
|
+
import path from "path";
|
|
26
|
+
|
|
27
|
+
const COLUMN: string = "isCriticalAlertEnabled";
|
|
28
|
+
|
|
29
|
+
const MIGRATIONS_DIR: string = path.join(
|
|
30
|
+
__dirname,
|
|
31
|
+
"..",
|
|
32
|
+
"..",
|
|
33
|
+
"Server",
|
|
34
|
+
"Infrastructure",
|
|
35
|
+
"Postgres",
|
|
36
|
+
"SchemaMigrations",
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const MIGRATION_CLASS: string = "MigrationName1787156982416";
|
|
40
|
+
|
|
41
|
+
const MIGRATION_PATH: string = path.join(
|
|
42
|
+
MIGRATIONS_DIR,
|
|
43
|
+
"1787156982416-MigrationName.ts",
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
function metadata(): TableColumnMetadata {
|
|
47
|
+
return new UserPush().getTableColumnMetadata(COLUMN);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function typeOrmColumn(): ColumnMetadataArgs | undefined {
|
|
51
|
+
return getMetadataArgsStorage().columns.find((column: ColumnMetadataArgs) => {
|
|
52
|
+
return column.target === UserPush && column.propertyName === COLUMN;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
describe("UserPush.isCriticalAlertEnabled", () => {
|
|
57
|
+
test("exists as a boolean column", () => {
|
|
58
|
+
expect(metadata()).toBeDefined();
|
|
59
|
+
expect(metadata().type).toBe(TableColumnType.Boolean);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("a newly registered device does NOT override silent mode", () => {
|
|
63
|
+
/*
|
|
64
|
+
* The single most important assertion in this file. Overriding a silenced
|
|
65
|
+
* phone is opted into, never inherited: a responder who installs the app
|
|
66
|
+
* has not asked to be woken by it, and a default of true would make every
|
|
67
|
+
* existing user's phone start ringing through Do Not Disturb on upgrade.
|
|
68
|
+
*/
|
|
69
|
+
expect(typeOrmColumn()).toBeDefined();
|
|
70
|
+
expect(typeOrmColumn()?.options.default).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("every device that existed before this feature was backfilled as off", () => {
|
|
74
|
+
const migration: string = fs.readFileSync(MIGRATION_PATH, "utf8");
|
|
75
|
+
|
|
76
|
+
expect(migration).toContain('ALTER TABLE "UserPush"');
|
|
77
|
+
expect(migration).toContain(
|
|
78
|
+
`ADD "${COLUMN}" boolean NOT NULL DEFAULT false`,
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("the migration is registered, so the column actually exists at runtime", () => {
|
|
83
|
+
/*
|
|
84
|
+
* A migration file missing from Index.ts never runs. The column would then
|
|
85
|
+
* be absent from Postgres while every select in the paging path asks for
|
|
86
|
+
* it, which fails the query that sends the page.
|
|
87
|
+
*/
|
|
88
|
+
const index: string = fs.readFileSync(
|
|
89
|
+
path.join(MIGRATIONS_DIR, "Index.ts"),
|
|
90
|
+
"utf8",
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// Imported AND listed in the exported array - the import alone does nothing.
|
|
94
|
+
expect(index.match(new RegExp(MIGRATION_CLASS, "g"))?.length).toBe(2);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("the migration's down() removes the column", () => {
|
|
98
|
+
const migration: string = fs.readFileSync(MIGRATION_PATH, "utf8");
|
|
99
|
+
|
|
100
|
+
expect(migration).toContain(
|
|
101
|
+
`ALTER TABLE "UserPush" DROP COLUMN "${COLUMN}"`,
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("is a default-value column, so existing create calls keep working", () => {
|
|
106
|
+
expect(new UserPush().isDefaultValueColumn(COLUMN)).toBe(true);
|
|
107
|
+
expect(metadata().required).toBeFalsy();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("is documented as defaulting to off", () => {
|
|
111
|
+
expect(metadata().defaultValue).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe("UserPush.isCriticalAlertEnabled access control", () => {
|
|
116
|
+
/*
|
|
117
|
+
* UserPush is an owner-only table: its table-level `read` names
|
|
118
|
+
* Permission.CurrentUser and nothing else, which is what scopes every read
|
|
119
|
+
* to the caller's own rows. A new column has to keep that shape or it
|
|
120
|
+
* becomes the exception that widens the table.
|
|
121
|
+
*/
|
|
122
|
+
test("is readable only by the responder it belongs to", () => {
|
|
123
|
+
const read: Array<Permission> | undefined =
|
|
124
|
+
new UserPush().getColumnAccessControlFor(COLUMN)?.read;
|
|
125
|
+
|
|
126
|
+
expect(read).toEqual([Permission.CurrentUser]);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("is settable at registration by the responder", () => {
|
|
130
|
+
const create: Array<Permission> | undefined =
|
|
131
|
+
new UserPush().getColumnAccessControlFor(COLUMN)?.create;
|
|
132
|
+
|
|
133
|
+
expect(create).toEqual([Permission.CurrentUser]);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("cannot be written through the generic CRUD update surface", () => {
|
|
137
|
+
/*
|
|
138
|
+
* Every column on this model has an empty update list; writes go through
|
|
139
|
+
* the dedicated routes that check row ownership first and then act as
|
|
140
|
+
* root. Granting update here would let the flag be flipped by any path
|
|
141
|
+
* that can PUT the model, which is a wider surface than "the phone that
|
|
142
|
+
* owns this row".
|
|
143
|
+
*/
|
|
144
|
+
const update: Array<Permission> | undefined =
|
|
145
|
+
new UserPush().getColumnAccessControlFor(COLUMN)?.update;
|
|
146
|
+
|
|
147
|
+
expect(update).toEqual([]);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("does not widen the table's owner-only read scope", () => {
|
|
151
|
+
/*
|
|
152
|
+
* isAccessGrantedOnlyByCurrentUser is true exactly while the TABLE read
|
|
153
|
+
* list holds nothing but CurrentUser, and that is what stamps
|
|
154
|
+
* `userId = me` onto every read of this table. Adding a column must not
|
|
155
|
+
* disturb it.
|
|
156
|
+
*/
|
|
157
|
+
expect(new UserPush().getReadPermissions()).toEqual([
|
|
158
|
+
Permission.CurrentUser,
|
|
159
|
+
]);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test("is not marked readable through relation queries", () => {
|
|
163
|
+
/*
|
|
164
|
+
* canReadOnRelationQuery makes a column readable from a nested select on a
|
|
165
|
+
* model whose own read is admin-wide, skipping this table's column check
|
|
166
|
+
* entirely. isVerified - the column this one sits beside and is read
|
|
167
|
+
* alongside - does not set it, and neither does this: the paging path
|
|
168
|
+
* reads both as root, so nothing needs the flag.
|
|
169
|
+
*/
|
|
170
|
+
expect(metadata().canReadOnRelationQuery).toBeFalsy();
|
|
171
|
+
});
|
|
172
|
+
});
|