@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,458 @@
|
|
|
1
|
+
import UserNotificationRuleService from "../../../Server/Services/UserNotificationRuleService";
|
|
2
|
+
import UserOnCallLogService from "../../../Server/Services/UserOnCallLogService";
|
|
3
|
+
import UserOnCallLogTimelineService from "../../../Server/Services/UserOnCallLogTimelineService";
|
|
4
|
+
import ProjectCallSMSConfigService from "../../../Server/Services/ProjectCallSMSConfigService";
|
|
5
|
+
import IncidentService from "../../../Server/Services/IncidentService";
|
|
6
|
+
import AlertService from "../../../Server/Services/AlertService";
|
|
7
|
+
import AlertEpisodeService from "../../../Server/Services/AlertEpisodeService";
|
|
8
|
+
import IncidentEpisodeService from "../../../Server/Services/IncidentEpisodeService";
|
|
9
|
+
import PushNotificationService from "../../../Server/Services/PushNotificationService";
|
|
10
|
+
import logger from "../../../Server/Utils/Logger";
|
|
11
|
+
import Incident from "../../../Models/DatabaseModels/Incident";
|
|
12
|
+
import Alert from "../../../Models/DatabaseModels/Alert";
|
|
13
|
+
import AlertEpisode from "../../../Models/DatabaseModels/AlertEpisode";
|
|
14
|
+
import IncidentEpisode from "../../../Models/DatabaseModels/IncidentEpisode";
|
|
15
|
+
import UserNotificationRule from "../../../Models/DatabaseModels/UserNotificationRule";
|
|
16
|
+
import UserPush from "../../../Models/DatabaseModels/UserPush";
|
|
17
|
+
import PushNotificationRequest from "../../../Types/PushNotification/PushNotificationRequest";
|
|
18
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
19
|
+
import URL from "../../../Types/API/URL";
|
|
20
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
21
|
+
import NotificationRuleType from "../../../Types/NotificationRule/NotificationRuleType";
|
|
22
|
+
import PushDeviceType from "../../../Types/PushNotification/PushDeviceType";
|
|
23
|
+
import UserNotificationEventType from "../../../Types/UserNotification/UserNotificationEventType";
|
|
24
|
+
import { describe, expect, test, beforeEach, afterEach } from "@jest/globals";
|
|
25
|
+
|
|
26
|
+
/*
|
|
27
|
+
* The on-call paging path is the ONLY place in the product allowed to send a
|
|
28
|
+
* notification that overrides a silenced phone, and it may only do so for a
|
|
29
|
+
* device whose owner turned the option on. Both halves of that sentence are
|
|
30
|
+
* load-bearing and neither fails loudly:
|
|
31
|
+
*
|
|
32
|
+
* - a page that loses the flag arrives silently, and the responder sleeps
|
|
33
|
+
* through the incident. Nothing logs an error; the page was "delivered".
|
|
34
|
+
* - a page that gains the flag it should not have wakes somebody who asked
|
|
35
|
+
* not to be woken, which is how an on-call app gets its notifications
|
|
36
|
+
* switched off entirely.
|
|
37
|
+
*
|
|
38
|
+
* So this file drives the real delivery half with a real UserPush model and
|
|
39
|
+
* inspects what was actually handed to the sender, for every event type that
|
|
40
|
+
* pages a responder.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
44
|
+
"11111111-1111-4111-8111-111111111111",
|
|
45
|
+
);
|
|
46
|
+
const LOG_ID: ObjectID = new ObjectID("22222222-2222-4222-8222-222222222222");
|
|
47
|
+
const RULE_ID: ObjectID = new ObjectID("33333333-3333-4333-8333-333333333333");
|
|
48
|
+
const USER_ID: ObjectID = new ObjectID("44444444-4444-4444-8444-444444444444");
|
|
49
|
+
const INCIDENT_ID: ObjectID = new ObjectID(
|
|
50
|
+
"55555555-5555-4555-8555-555555555555",
|
|
51
|
+
);
|
|
52
|
+
const ALERT_ID: ObjectID = new ObjectID("66666666-6666-4666-8666-666666666666");
|
|
53
|
+
const ALERT_EPISODE_ID: ObjectID = new ObjectID(
|
|
54
|
+
"77777777-7777-4777-8777-777777777777",
|
|
55
|
+
);
|
|
56
|
+
const INCIDENT_EPISODE_ID: ObjectID = new ObjectID(
|
|
57
|
+
"88888888-8888-4888-8888-888888888888",
|
|
58
|
+
);
|
|
59
|
+
const TIMELINE_ID: ObjectID = new ObjectID(
|
|
60
|
+
"99999999-9999-4999-8999-999999999999",
|
|
61
|
+
);
|
|
62
|
+
const PUSH_METHOD_ID: ObjectID = new ObjectID(
|
|
63
|
+
"dddddddd-dddd-4ddd-8ddd-dddddddddddd",
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const DEVICE_TOKEN: string = "ExponentPushToken[test-device]";
|
|
67
|
+
|
|
68
|
+
type ExecuteOptions = Parameters<
|
|
69
|
+
typeof UserNotificationRuleService.executeNotificationRuleItem
|
|
70
|
+
>[1];
|
|
71
|
+
|
|
72
|
+
/*
|
|
73
|
+
* deliverNotificationForRule is private, so TypeScript will not let a test name
|
|
74
|
+
* it. It is an ordinary prototype method at runtime and the on-call fallback
|
|
75
|
+
* already calls it with an unsaved rule, so it is reached through a structural
|
|
76
|
+
* cast - the same approach the neighbouring test files use.
|
|
77
|
+
*/
|
|
78
|
+
interface DeliveryHalf {
|
|
79
|
+
deliverNotificationForRule: (
|
|
80
|
+
notificationRuleItem: UserNotificationRule,
|
|
81
|
+
options: ExecuteOptions,
|
|
82
|
+
) => Promise<boolean>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function deliveryHalf(): DeliveryHalf {
|
|
86
|
+
return UserNotificationRuleService as unknown as DeliveryHalf;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function userPushDevice(options: {
|
|
90
|
+
isCriticalAlertEnabled?: boolean;
|
|
91
|
+
deviceType?: PushDeviceType;
|
|
92
|
+
}): UserPush {
|
|
93
|
+
const userPush: UserPush = new UserPush();
|
|
94
|
+
userPush._id = PUSH_METHOD_ID.toString();
|
|
95
|
+
userPush.deviceToken = DEVICE_TOKEN;
|
|
96
|
+
userPush.deviceType = options.deviceType ?? PushDeviceType.iOS;
|
|
97
|
+
userPush.isVerified = true;
|
|
98
|
+
userPush.userId = USER_ID;
|
|
99
|
+
|
|
100
|
+
if (options.isCriticalAlertEnabled !== undefined) {
|
|
101
|
+
userPush.isCriticalAlertEnabled = options.isCriticalAlertEnabled;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return userPush;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function pushOnlyRule(device: UserPush): UserNotificationRule {
|
|
108
|
+
const rule: UserNotificationRule = new UserNotificationRule();
|
|
109
|
+
rule.projectId = PROJECT_ID;
|
|
110
|
+
rule.userId = USER_ID;
|
|
111
|
+
rule.ruleType = NotificationRuleType.ON_CALL_EXECUTED_INCIDENT;
|
|
112
|
+
rule.notifyAfterMinutes = 0;
|
|
113
|
+
rule.userPush = device;
|
|
114
|
+
rule.userPushId = PUSH_METHOD_ID;
|
|
115
|
+
|
|
116
|
+
return rule;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/*
|
|
120
|
+
* The delivery half loads the thing being paged about from whichever
|
|
121
|
+
* triggeredBy* id matches the event type, and refuses outright if none of them
|
|
122
|
+
* resolves. So the id has to travel with the event type rather than being set
|
|
123
|
+
* once - a mismatch here fails as "Incident, Alert, Alert Episode, or Incident
|
|
124
|
+
* Episode not found", a long way from the pairing that caused it.
|
|
125
|
+
*/
|
|
126
|
+
const TRIGGER_ID_FOR_EVENT: Record<string, Partial<ExecuteOptions>> = {
|
|
127
|
+
[UserNotificationEventType.IncidentCreated]: {
|
|
128
|
+
triggeredByIncidentId: INCIDENT_ID,
|
|
129
|
+
},
|
|
130
|
+
[UserNotificationEventType.AlertCreated]: {
|
|
131
|
+
triggeredByAlertId: ALERT_ID,
|
|
132
|
+
},
|
|
133
|
+
[UserNotificationEventType.AlertEpisodeCreated]: {
|
|
134
|
+
triggeredByAlertEpisodeId: ALERT_EPISODE_ID,
|
|
135
|
+
},
|
|
136
|
+
[UserNotificationEventType.IncidentEpisodeCreated]: {
|
|
137
|
+
triggeredByIncidentEpisodeId: INCIDENT_EPISODE_ID,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
function executeOptions(
|
|
142
|
+
overrides: Partial<ExecuteOptions> = {},
|
|
143
|
+
): ExecuteOptions {
|
|
144
|
+
const eventType: UserNotificationEventType =
|
|
145
|
+
(overrides as { userNotificationEventType?: UserNotificationEventType })
|
|
146
|
+
.userNotificationEventType ?? UserNotificationEventType.IncidentCreated;
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
projectId: PROJECT_ID,
|
|
150
|
+
userNotificationEventType: eventType,
|
|
151
|
+
userNotificationLogId: LOG_ID,
|
|
152
|
+
...TRIGGER_ID_FOR_EVENT[eventType],
|
|
153
|
+
...overrides,
|
|
154
|
+
} as ExecuteOptions;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function fakeIncident(): Incident {
|
|
158
|
+
return {
|
|
159
|
+
id: INCIDENT_ID,
|
|
160
|
+
projectId: PROJECT_ID,
|
|
161
|
+
title: "Checkout is down",
|
|
162
|
+
incidentNumber: 42,
|
|
163
|
+
incidentNumberWithPrefix: "INC-42",
|
|
164
|
+
} as unknown as Incident;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function fakeAlert(): Alert {
|
|
168
|
+
return {
|
|
169
|
+
id: ALERT_ID,
|
|
170
|
+
projectId: PROJECT_ID,
|
|
171
|
+
title: "Disk almost full",
|
|
172
|
+
alertNumber: 7,
|
|
173
|
+
alertNumberWithPrefix: "ALT-7",
|
|
174
|
+
} as unknown as Alert;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function fakeAlertEpisode(): AlertEpisode {
|
|
178
|
+
return {
|
|
179
|
+
id: ALERT_EPISODE_ID,
|
|
180
|
+
projectId: PROJECT_ID,
|
|
181
|
+
title: "Disk pressure across the fleet",
|
|
182
|
+
episodeNumber: 3,
|
|
183
|
+
} as unknown as AlertEpisode;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function fakeIncidentEpisode(): IncidentEpisode {
|
|
187
|
+
return {
|
|
188
|
+
id: INCIDENT_EPISODE_ID,
|
|
189
|
+
projectId: PROJECT_ID,
|
|
190
|
+
title: "Payments degraded",
|
|
191
|
+
episodeNumber: 4,
|
|
192
|
+
} as unknown as IncidentEpisode;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
describe("On-call push notifications and the critical alert flag", () => {
|
|
196
|
+
let pushSpy: jest.SpyInstance;
|
|
197
|
+
|
|
198
|
+
beforeEach(() => {
|
|
199
|
+
jest.spyOn(logger, "error").mockImplementation((): void => {
|
|
200
|
+
return undefined;
|
|
201
|
+
});
|
|
202
|
+
jest.spyOn(logger, "warn").mockImplementation((): void => {
|
|
203
|
+
return undefined;
|
|
204
|
+
});
|
|
205
|
+
jest.spyOn(logger, "info").mockImplementation((): void => {
|
|
206
|
+
return undefined;
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
jest
|
|
210
|
+
.spyOn(UserOnCallLogService, "claimNotificationRuleExecution")
|
|
211
|
+
.mockResolvedValue(true as never);
|
|
212
|
+
|
|
213
|
+
jest
|
|
214
|
+
.spyOn(UserOnCallLogTimelineService, "create")
|
|
215
|
+
.mockResolvedValue({ id: TIMELINE_ID } as unknown as never);
|
|
216
|
+
|
|
217
|
+
jest
|
|
218
|
+
.spyOn(UserOnCallLogTimelineService, "updateOneById")
|
|
219
|
+
.mockResolvedValue(undefined as never);
|
|
220
|
+
|
|
221
|
+
jest
|
|
222
|
+
.spyOn(ProjectCallSMSConfigService, "getProjectDefaultTwilioConfig")
|
|
223
|
+
.mockResolvedValue(undefined as never);
|
|
224
|
+
|
|
225
|
+
jest
|
|
226
|
+
.spyOn(IncidentService, "findOneById")
|
|
227
|
+
.mockResolvedValue(fakeIncident() as never);
|
|
228
|
+
jest
|
|
229
|
+
.spyOn(IncidentService, "getIncidentLinkInDashboard")
|
|
230
|
+
.mockResolvedValue(
|
|
231
|
+
URL.fromString("https://dashboard.example.com/incident") as never,
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
jest
|
|
235
|
+
.spyOn(AlertService, "findOneById")
|
|
236
|
+
.mockResolvedValue(fakeAlert() as never);
|
|
237
|
+
jest
|
|
238
|
+
.spyOn(AlertService, "getAlertLinkInDashboard")
|
|
239
|
+
.mockResolvedValue(
|
|
240
|
+
URL.fromString("https://dashboard.example.com/alert") as never,
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
jest
|
|
244
|
+
.spyOn(AlertEpisodeService, "findOneById")
|
|
245
|
+
.mockResolvedValue(fakeAlertEpisode() as never);
|
|
246
|
+
jest
|
|
247
|
+
.spyOn(IncidentEpisodeService, "findOneById")
|
|
248
|
+
.mockResolvedValue(fakeIncidentEpisode() as never);
|
|
249
|
+
|
|
250
|
+
pushSpy = jest
|
|
251
|
+
.spyOn(PushNotificationService, "sendPushNotification")
|
|
252
|
+
.mockResolvedValue(undefined as never);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
afterEach(() => {
|
|
256
|
+
jest.restoreAllMocks();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
function sentRequest(): PushNotificationRequest {
|
|
260
|
+
expect(pushSpy).toHaveBeenCalledTimes(1);
|
|
261
|
+
return pushSpy.mock.calls[0]![0] as PushNotificationRequest;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const pagingEvents: Array<[string, UserNotificationEventType]> = [
|
|
265
|
+
["an incident", UserNotificationEventType.IncidentCreated],
|
|
266
|
+
["an alert", UserNotificationEventType.AlertCreated],
|
|
267
|
+
["an alert episode", UserNotificationEventType.AlertEpisodeCreated],
|
|
268
|
+
["an incident episode", UserNotificationEventType.IncidentEpisodeCreated],
|
|
269
|
+
];
|
|
270
|
+
|
|
271
|
+
describe("a device that opted in is paged as a critical alert", () => {
|
|
272
|
+
test.each(pagingEvents)(
|
|
273
|
+
"%s page overrides silent mode",
|
|
274
|
+
async (_label: string, eventType: UserNotificationEventType) => {
|
|
275
|
+
const rule: UserNotificationRule = pushOnlyRule(
|
|
276
|
+
userPushDevice({ isCriticalAlertEnabled: true }),
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
await deliveryHalf().deliverNotificationForRule(
|
|
280
|
+
rule,
|
|
281
|
+
executeOptions({ userNotificationEventType: eventType }),
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
expect(sentRequest().message.isCriticalAlert).toBe(true);
|
|
285
|
+
},
|
|
286
|
+
);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
describe("a device that did not opt in is paged normally", () => {
|
|
290
|
+
test.each(pagingEvents)(
|
|
291
|
+
"%s page respects the ringer switch when the flag is false",
|
|
292
|
+
async (_label: string, eventType: UserNotificationEventType) => {
|
|
293
|
+
const rule: UserNotificationRule = pushOnlyRule(
|
|
294
|
+
userPushDevice({ isCriticalAlertEnabled: false }),
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
await deliveryHalf().deliverNotificationForRule(
|
|
298
|
+
rule,
|
|
299
|
+
executeOptions({ userNotificationEventType: eventType }),
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
expect(sentRequest().message.isCriticalAlert).toBe(false);
|
|
303
|
+
},
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
test.each(pagingEvents)(
|
|
307
|
+
"%s page respects the ringer switch when the column was never set",
|
|
308
|
+
async (_label: string, eventType: UserNotificationEventType) => {
|
|
309
|
+
/*
|
|
310
|
+
* Every device registered before this feature shipped reads back as
|
|
311
|
+
* undefined until the migration's default is loaded. Undefined must
|
|
312
|
+
* behave as "off" rather than as "unknown, escalate anyway".
|
|
313
|
+
*/
|
|
314
|
+
const rule: UserNotificationRule = pushOnlyRule(userPushDevice({}));
|
|
315
|
+
|
|
316
|
+
await deliveryHalf().deliverNotificationForRule(
|
|
317
|
+
rule,
|
|
318
|
+
executeOptions({ userNotificationEventType: eventType }),
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
expect(sentRequest().message.isCriticalAlert).toBe(false);
|
|
322
|
+
},
|
|
323
|
+
);
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
describe("the flag travels with the page, not instead of it", () => {
|
|
327
|
+
test("the page still carries its title, body and device", async () => {
|
|
328
|
+
const rule: UserNotificationRule = pushOnlyRule(
|
|
329
|
+
userPushDevice({ isCriticalAlertEnabled: true }),
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
await deliveryHalf().deliverNotificationForRule(rule, executeOptions());
|
|
333
|
+
|
|
334
|
+
const request: PushNotificationRequest = sentRequest();
|
|
335
|
+
|
|
336
|
+
expect(request.devices).toEqual([{ token: DEVICE_TOKEN }]);
|
|
337
|
+
expect(request.deviceType).toBe(PushDeviceType.iOS);
|
|
338
|
+
expect(request.message.title).toContain("Checkout is down");
|
|
339
|
+
expect(request.message.body.length).toBeGreaterThan(0);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
test("an Android device gets the flag too", async () => {
|
|
343
|
+
const rule: UserNotificationRule = pushOnlyRule(
|
|
344
|
+
userPushDevice({
|
|
345
|
+
isCriticalAlertEnabled: true,
|
|
346
|
+
deviceType: PushDeviceType.Android,
|
|
347
|
+
}),
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
await deliveryHalf().deliverNotificationForRule(rule, executeOptions());
|
|
351
|
+
|
|
352
|
+
const request: PushNotificationRequest = sentRequest();
|
|
353
|
+
|
|
354
|
+
expect(request.deviceType).toBe(PushDeviceType.Android);
|
|
355
|
+
expect(request.message.isCriticalAlert).toBe(true);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
test("the on-call log timeline still records the push attempt", async () => {
|
|
359
|
+
const rule: UserNotificationRule = pushOnlyRule(
|
|
360
|
+
userPushDevice({ isCriticalAlertEnabled: true }),
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
await deliveryHalf().deliverNotificationForRule(rule, executeOptions());
|
|
364
|
+
|
|
365
|
+
expect(UserOnCallLogTimelineService.create).toHaveBeenCalled();
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
describe("an unverified device is not paged at all", () => {
|
|
370
|
+
test("opting into critical alerts does not bypass verification", async () => {
|
|
371
|
+
/*
|
|
372
|
+
* The critical flag decides HOW a page sounds, never WHETHER it is sent.
|
|
373
|
+
* A device that was never verified must stay silent regardless.
|
|
374
|
+
*/
|
|
375
|
+
const device: UserPush = userPushDevice({
|
|
376
|
+
isCriticalAlertEnabled: true,
|
|
377
|
+
});
|
|
378
|
+
device.isVerified = false;
|
|
379
|
+
|
|
380
|
+
const rule: UserNotificationRule = pushOnlyRule(device);
|
|
381
|
+
|
|
382
|
+
await deliveryHalf().deliverNotificationForRule(rule, executeOptions());
|
|
383
|
+
|
|
384
|
+
expect(pushSpy).not.toHaveBeenCalled();
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
describe("The rule select loads the critical alert flag", () => {
|
|
390
|
+
/*
|
|
391
|
+
* An unselected column arrives as undefined, which the delivery half reads
|
|
392
|
+
* as "not opted in". So dropping this field from the select does not error -
|
|
393
|
+
* it silently downgrades every critical page in the product to a normal one.
|
|
394
|
+
* That is a one-line change with no visible symptom until somebody sleeps
|
|
395
|
+
* through an incident, which is exactly the kind of regression a test has to
|
|
396
|
+
* hold.
|
|
397
|
+
*/
|
|
398
|
+
let findSpy: jest.SpyInstance;
|
|
399
|
+
|
|
400
|
+
beforeEach(() => {
|
|
401
|
+
jest.spyOn(logger, "error").mockImplementation((): void => {
|
|
402
|
+
return undefined;
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
jest
|
|
406
|
+
.spyOn(UserOnCallLogService, "claimNotificationRuleExecution")
|
|
407
|
+
.mockResolvedValue(true as never);
|
|
408
|
+
|
|
409
|
+
jest
|
|
410
|
+
.spyOn(deliveryHalf(), "deliverNotificationForRule")
|
|
411
|
+
.mockResolvedValue(true as never);
|
|
412
|
+
|
|
413
|
+
findSpy = jest
|
|
414
|
+
.spyOn(UserNotificationRuleService, "findOneById")
|
|
415
|
+
.mockResolvedValue({
|
|
416
|
+
id: RULE_ID,
|
|
417
|
+
_id: RULE_ID.toString(),
|
|
418
|
+
userId: USER_ID,
|
|
419
|
+
} as unknown as never);
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
afterEach(() => {
|
|
423
|
+
jest.restoreAllMocks();
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
test("userPush.isCriticalAlertEnabled is selected", async () => {
|
|
427
|
+
await UserNotificationRuleService.executeNotificationRuleItem(
|
|
428
|
+
RULE_ID,
|
|
429
|
+
executeOptions(),
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
const select: JSONObject = (
|
|
433
|
+
findSpy.mock.calls[0]![0] as { select: JSONObject }
|
|
434
|
+
).select;
|
|
435
|
+
|
|
436
|
+
const userPushSelect: JSONObject = select["userPush"] as JSONObject;
|
|
437
|
+
|
|
438
|
+
expect(userPushSelect["isCriticalAlertEnabled"]).toBe(true);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
test("the columns the push branch already depended on are still selected", async () => {
|
|
442
|
+
await UserNotificationRuleService.executeNotificationRuleItem(
|
|
443
|
+
RULE_ID,
|
|
444
|
+
executeOptions(),
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
const select: JSONObject = (
|
|
448
|
+
findSpy.mock.calls[0]![0] as { select: JSONObject }
|
|
449
|
+
).select;
|
|
450
|
+
|
|
451
|
+
const userPushSelect: JSONObject = select["userPush"] as JSONObject;
|
|
452
|
+
|
|
453
|
+
expect(userPushSelect["deviceToken"]).toBe(true);
|
|
454
|
+
expect(userPushSelect["deviceType"]).toBe(true);
|
|
455
|
+
expect(userPushSelect["isVerified"]).toBe(true);
|
|
456
|
+
expect(userPushSelect["userId"]).toBe(true);
|
|
457
|
+
});
|
|
458
|
+
});
|