@oneuptime/common 12.0.8 → 12.0.9
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/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +1 -1
- package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +1 -1
- package/Models/DatabaseModels/AIConversation.ts +32 -0
- package/Models/DatabaseModels/AIConversationMessage.ts +41 -0
- package/Models/DatabaseModels/AlertEpisodeMember.ts +27 -0
- package/Models/DatabaseModels/IncidentEpisodeMember.ts +28 -0
- package/Models/DatabaseModels/Index.ts +12 -4
- package/Models/DatabaseModels/{TelemetryEntity.ts → InventoryItem.ts} +139 -9
- package/Models/DatabaseModels/InventoryItemCustomField.ts +434 -0
- package/Models/DatabaseModels/{TelemetryEntityRelationship.ts → InventoryItemRelationship.ts} +8 -8
- package/Models/DatabaseModels/NetworkDevice.ts +141 -0
- package/Models/DatabaseModels/NetworkDeviceLink.ts +699 -0
- package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +467 -0
- package/Models/DatabaseModels/NetworkTopologySuppression.ts +429 -0
- package/Models/DatabaseModels/OnCallDutyPolicyFeed.ts +9 -0
- package/Models/DatabaseModels/Project.ts +78 -0
- package/Models/DatabaseModels/UserCall.ts +42 -0
- package/Models/DatabaseModels/UserEmail.ts +44 -0
- package/Models/DatabaseModels/UserNotificationRule.ts +425 -55
- package/Models/DatabaseModels/UserOnCallLogTimeline.ts +24 -2
- package/Models/DatabaseModels/UserPush.ts +49 -0
- package/Models/DatabaseModels/UserSMS.ts +43 -0
- package/Models/DatabaseModels/UserTelegram.ts +59 -0
- package/Models/DatabaseModels/UserWebhook.ts +52 -0
- package/Models/DatabaseModels/UserWhatsApp.ts +41 -0
- package/Models/DatabaseModels/WorkflowVariable.ts +12 -0
- package/Server/API/AIChatAPI.ts +315 -1
- package/Server/API/DashboardAPI.ts +217 -1
- package/Server/API/OnCallReadinessAPI.ts +841 -0
- package/Server/API/TeamComplianceAPI.ts +69 -17
- package/Server/API/TelemetryAPI.ts +220 -12
- package/Server/EnvironmentConfig.ts +52 -0
- package/Server/Infrastructure/Postgres/DataSourceOptions.ts +22 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.ts +4 -4
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.ts +5 -5
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.ts +35 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.ts +82 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.ts +91 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.ts +255 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.ts +107 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.ts +90 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.ts +39 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.ts +59 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +20 -0
- package/Server/Infrastructure/Queue.ts +78 -13
- package/Server/Middleware/PublicDashboardRateLimit.ts +593 -0
- package/Server/Services/AIService.ts +7 -0
- package/Server/Services/AlertEpisodeStateTimelineService.ts +29 -0
- package/Server/Services/AlertSeverityService.ts +63 -0
- package/Server/Services/DashboardService.ts +9 -10
- package/Server/Services/DatabaseService.ts +32 -2
- package/Server/Services/IncidentEpisodeStateTimelineService.ts +29 -0
- package/Server/Services/IncidentSeverityService.ts +76 -0
- package/Server/Services/Index.ts +12 -4
- package/Server/Services/InventoryItemCustomFieldService.ts +9 -0
- package/Server/Services/{TelemetryEntityRelationshipService.ts → InventoryItemRelationshipService.ts} +4 -4
- package/Server/Services/{TelemetryEntityService.ts → InventoryItemService.ts} +89 -20
- package/Server/Services/LogAggregationService.ts +45 -8
- package/Server/Services/MetricAggregationService.ts +121 -0
- package/Server/Services/MetricService.ts +7 -7
- package/Server/Services/NetworkDeviceLinkRuleService.ts +10 -0
- package/Server/Services/NetworkDeviceLinkService.ts +84 -0
- package/Server/Services/NetworkDeviceService.ts +140 -0
- package/Server/Services/NetworkSiteService.ts +77 -25
- package/Server/Services/NetworkTopologySuppressionService.ts +84 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +41 -29
- package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +8 -0
- package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +62 -13
- package/Server/Services/OnCallDutyPolicyScheduleService.ts +61 -1
- package/Server/Services/OnCallNotificationAlertingService.ts +742 -0
- package/Server/Services/OnCallReadinessService.ts +2803 -0
- package/Server/Services/OnCallSetupReminderService.ts +955 -0
- package/Server/Services/ProfileAggregationService.ts +123 -0
- package/Server/Services/StatusPageService.ts +9 -10
- package/Server/Services/TeamComplianceService.ts +429 -252
- package/Server/Services/UserCallService.ts +26 -1
- package/Server/Services/UserEmailService.ts +26 -1
- package/Server/Services/UserNotificationRuleAdminService.ts +1183 -0
- package/Server/Services/UserNotificationRuleService.ts +3812 -333
- package/Server/Services/UserOnCallLogService.ts +561 -48
- package/Server/Services/UserPushService.ts +29 -0
- package/Server/Services/UserService.ts +11 -0
- package/Server/Services/UserSmsService.ts +26 -1
- package/Server/Services/UserTelegramService.ts +24 -1
- package/Server/Services/UserWebhookService.ts +28 -1
- package/Server/Services/UserWhatsAppService.ts +24 -1
- package/Server/Types/Database/Permissions/BasePermission.ts +19 -0
- package/Server/Types/Database/Permissions/CreatePermission.ts +164 -0
- package/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.ts +340 -0
- package/Server/Types/Database/Permissions/QueryPermission.ts +48 -0
- package/Server/Types/Database/Permissions/TenantPermission.ts +8 -1
- package/Server/Types/Workflow/Components/API/Delete.ts +1 -1
- package/Server/Types/Workflow/Components/API/Get.ts +1 -1
- package/Server/Types/Workflow/Components/API/Patch.ts +1 -1
- package/Server/Types/Workflow/Components/API/Post.ts +1 -1
- package/Server/Types/Workflow/Components/API/Put.ts +1 -1
- package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +29 -5
- package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +18 -10
- package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +55 -0
- package/Server/Types/Workflow/Components/Conditions/IfElse.ts +3 -17
- package/Server/Types/Workflow/Components/Email.ts +25 -7
- package/Server/Types/Workflow/Components/JavaScript.ts +10 -3
- package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +1 -1
- package/Server/Utils/AI/Chat/ChatAgentRunner.ts +643 -48
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +32 -3
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +20 -6
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +7 -0
- package/Server/Utils/AI/Toolbox/AIActionTools.ts +2 -2
- package/Server/Utils/AI/Toolbox/AIMetaTools.ts +863 -0
- package/Server/Utils/AI/Toolbox/AlertTools.ts +177 -15
- package/Server/Utils/AI/Toolbox/IncidentTools.ts +191 -10
- package/Server/Utils/AI/Toolbox/Index.ts +48 -0
- package/Server/Utils/AI/Toolbox/MonitorTools.ts +298 -11
- package/Server/Utils/AI/Toolbox/NoteWriteTools.ts +295 -0
- package/Server/Utils/AI/Toolbox/OnCallTools.ts +1246 -0
- package/Server/Utils/AI/Toolbox/RunbookTools.ts +424 -0
- package/Server/Utils/AI/Toolbox/SloTools.ts +456 -0
- package/Server/Utils/AI/Toolbox/StatusPageTools.ts +559 -0
- package/Server/Utils/AI/Toolbox/TeamTools.ts +327 -0
- package/Server/Utils/AI/Toolbox/TimelineTools.ts +615 -0
- package/Server/Utils/AI/Toolbox/WorkflowProbeTools.ts +664 -0
- package/Server/Utils/ClientIp.ts +221 -0
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +47 -0
- package/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.ts +163 -0
- package/Server/Utils/Dashboard/PublicDashboardSloWidget.ts +147 -0
- package/Server/Utils/Express.ts +12 -17
- package/Server/Utils/LLM/LLMService.ts +85 -8
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +204 -10
- package/Server/Utils/SSRFProtection.ts +98 -23
- package/Server/Utils/StartServer.ts +12 -3
- package/Server/Utils/Telemetry/EntityRegistry.ts +205 -18
- package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +25 -25
- package/Server/Utils/Telemetry/TelemetryEntity.ts +160 -52
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +7 -3
- package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +2146 -0
- package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +561 -0
- package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +2470 -0
- package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +1897 -0
- package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3606 -0
- package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +784 -0
- package/Tests/App/Dashboard/OnCallRulesTable.test.tsx +1119 -0
- package/Tests/App/Dashboard/SloWidgetFetching.test.tsx +531 -0
- package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +1312 -0
- package/Tests/App/Dashboard/UserSettingsSetupChecklistPage.test.tsx +1390 -0
- package/Tests/Models/InventoryItemModel.test.ts +174 -0
- package/Tests/Models/InventoryItemNaming.test.ts +302 -0
- package/Tests/Server/API/AIChatCancelAndFeedback.test.ts +437 -0
- package/Tests/Server/API/DashboardPublicRateLimit.test.ts +659 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +18 -0
- package/Tests/Server/API/DashboardPublicSloAPI.test.ts +880 -0
- package/Tests/Server/API/Helpers.ts +24 -15
- package/Tests/Server/API/OnCallReadinessAPI.test.ts +2680 -0
- package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +915 -0
- package/Tests/Server/Infrastructure/Postgres/EpisodeMemberNotifyIndexesMigration.test.ts +533 -0
- package/Tests/Server/Infrastructure/Postgres/InventoryItemArchiveMigration.test.ts +213 -0
- package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +432 -0
- package/Tests/Server/Infrastructure/Queue.test.ts +293 -0
- package/Tests/Server/Middleware/PublicDashboardRateLimit.test.ts +1645 -0
- package/Tests/Server/Services/AdminRuleEditGuards.test.ts +2848 -0
- package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1393 -0
- package/Tests/Server/Services/EpisodeRuleSeverityRepair.test.ts +1802 -0
- package/Tests/Server/Services/EpisodeStateTimelineNote.test.ts +304 -0
- package/Tests/Server/Services/InventoryItemDisplayName.test.ts +339 -0
- package/Tests/Server/Services/{TelemetryEntityManualCreate.test.ts → InventoryItemManualCreate.test.ts} +27 -27
- package/Tests/Server/Services/IpAllowlistSpoofing.test.ts +450 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +235 -1
- package/Tests/Server/Services/MetricAggregationService.test.ts +231 -0
- package/Tests/Server/Services/MetricEntityMVKeyParity.test.ts +80 -29
- package/Tests/Server/Services/MetricServiceAggregate.test.ts +30 -30
- package/Tests/Server/Services/NetworkSiteService.test.ts +18 -3
- package/Tests/Server/Services/NotificationChannelEventCoverage.test.ts +1728 -0
- package/Tests/Server/Services/NotificationDeletionImpact.test.ts +2402 -0
- package/Tests/Server/Services/OnCallDutyPolicyExecutionLogTimelineGapFeed.test.ts +394 -0
- package/Tests/Server/Services/OnCallNotificationFallback.test.ts +1744 -0
- package/Tests/Server/Services/OnCallReadinessService.test.ts +4295 -0
- package/Tests/Server/Services/OnCallSetupReminder.test.ts +1272 -0
- package/Tests/Server/Services/OnCallWeeklyReadinessDigest.test.ts +1021 -0
- package/Tests/Server/Services/ProfileAggregationService.test.ts +296 -0
- package/Tests/Server/Services/SeverityCreationRuleBackfill.test.ts +1536 -0
- package/Tests/Server/Services/SeverityRuleBackfill.test.ts +1818 -0
- package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +1845 -0
- package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +1394 -0
- package/Tests/Server/Services/UserNotificationRuleDefaultCreation.test.ts +1166 -0
- package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1468 -0
- package/Tests/Server/Services/UserOnCallLogNoNotificationRules.test.ts +1457 -0
- package/Tests/Server/Types/Database/Permissions/AdminNotificationRuleAccess.test.ts +1546 -0
- package/Tests/Server/Types/Database/Permissions/CreateOwnershipScoping.test.ts +529 -0
- package/Tests/Server/Types/Database/Permissions/OwnerOnlyColumns.test.ts +1219 -0
- package/Tests/Server/Types/Database/Permissions/UserNotificationRuleScoping.test.ts +1089 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +2 -1
- package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +190 -0
- package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +44 -14
- package/Tests/Server/Types/Workflow/Components/Email.test.ts +151 -0
- package/Tests/Server/Types/Workflow/Components/IfElse.test.ts +98 -0
- package/Tests/Server/Types/Workflow/Components/JavaScript.test.ts +51 -0
- package/Tests/Server/Utils/AI/AIMetaTools.test.ts +586 -0
- package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +582 -0
- package/Tests/Server/Utils/AI/ChatAgentRunner.test.ts +726 -0
- package/Tests/Server/Utils/AI/IncidentToolsFilters.test.ts +315 -0
- package/Tests/Server/Utils/AI/LLMServiceStopReason.test.ts +314 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +26 -3
- package/Tests/Server/Utils/AI/NoteWriteTools.test.ts +268 -0
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +169 -0
- package/Tests/Server/Utils/AI/OnCallTools.test.ts +664 -0
- package/Tests/Server/Utils/AI/RunbookTools.test.ts +325 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +306 -0
- package/Tests/Server/Utils/AI/StatusPageTools.test.ts +391 -0
- package/Tests/Server/Utils/AI/TeamTools.test.ts +257 -0
- package/Tests/Server/Utils/AI/TimelineTools.test.ts +472 -0
- package/Tests/Server/Utils/AI/WorkflowProbeTools.test.ts +428 -0
- package/Tests/Server/Utils/ClientIp.test.ts +438 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +171 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.test.ts +383 -0
- package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +23 -25
- package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +6 -0
- package/Tests/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.test.ts +307 -0
- package/Tests/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.test.ts +468 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorTelemetryDeepLinks.test.ts +460 -0
- package/Tests/Server/Utils/ResponseRateLimitStatusCodes.test.ts +137 -0
- package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +40 -8
- package/Tests/Server/Utils/SSRFProtectionUserInfo.test.ts +351 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistryRetirement.test.ts +531 -0
- package/Tests/Server/Utils/Telemetry/InventoryEntityRegistry.test.ts +15 -15
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +356 -39
- package/Tests/Types/IP/IP.test.ts +263 -0
- package/Tests/Types/IP/IPWhitelist.test.ts +197 -0
- package/Tests/Types/IP/IPv6.test.ts +12 -1
- package/Tests/Types/Monitor/SnmpOid.test.ts +64 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +110 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeAudit.test.ts +106 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeDifferential.test.ts +511 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageEndToEnd.test.ts +489 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageGapTolerance.test.ts +479 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageState.test.ts +822 -0
- package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +6 -6
- package/Tests/Types/Workflow/BaseModelComponents.test.ts +429 -0
- package/Tests/Types/Workflow/Components/BaseModel.test.ts +225 -0
- package/Tests/Types/Workflow/IntegrationCredentialMetadata.test.ts +100 -0
- package/Tests/Types/Workflow/TemplateSyntax.test.ts +112 -0
- package/Tests/Types/Workflow/Templates.test.ts +916 -101
- package/Tests/UI/Components/ActiveFilterChipsOpenRoute.test.tsx +82 -0
- package/Tests/UI/Components/ComponentsModal.test.tsx +564 -7
- package/Tests/UI/Components/KeyboardShortcut.test.tsx +95 -0
- package/Tests/UI/Components/LogDetailsPanelCrossSignal.test.tsx +448 -0
- package/Tests/UI/Components/LogsTableCrossLinks.test.tsx +263 -0
- package/Tests/UI/Components/PendingProjectInvitations.test.tsx +913 -0
- package/Tests/UI/Components/SimpleLogViewer.test.tsx +228 -0
- package/Tests/UI/Components/TableRowSelectability.test.tsx +312 -0
- package/Tests/UI/Components/Workflow/GraphLint.test.ts +72 -0
- package/Tests/UI/Components/Workflow/GraphLintSummary.test.ts +755 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditor.test.ts +242 -7
- package/Tests/UI/Components/Workflow/ModelColumnEditorServerContract.test.ts +15 -7
- package/Tests/UI/Components/Workflow/ModelSchema.test.ts +242 -28
- package/Tests/UI/Components/Workflow/RunStatusWatcher.test.ts +59 -1
- package/Tests/UI/Components/Workflow/StepTraceViewer.test.tsx +256 -0
- package/Tests/UI/Components/Workflow/UseRunWatch.test.tsx +665 -0
- package/Tests/UI/Components/Workflow/WorkflowIssuesModal.test.tsx +485 -0
- package/Tests/UI/Components/Workflow/WorkflowLogModal.test.tsx +478 -0
- package/Tests/UI/Components/Workflow/WorkflowStatusBar.test.tsx +379 -0
- package/Tests/UI/EsbuildConfig.test.ts +607 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +5 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +11 -4
- package/Tests/UI/Utils/ModelAPICreateMiscData.test.ts +94 -0
- package/Tests/UI/Utils/Platform.test.ts +147 -0
- package/Tests/UI/Utils/ProjectInvitationDisplay.test.ts +357 -0
- package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +198 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +487 -0
- package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +698 -0
- package/Tests/__mocks__/bullmq.js +55 -0
- package/Types/AI/AIChatMessageStatus.ts +8 -1
- package/Types/AI/AIChatTypes.ts +12 -0
- package/Types/Database/AccessControl/OwnerOnlyColumn.ts +88 -0
- package/Types/Exception/ExceptionCode.ts +2 -0
- package/Types/Exception/ServiceUnavailableException.ts +8 -0
- package/Types/Exception/TooManyRequestsException.ts +8 -0
- package/Types/IP/IP.ts +93 -47
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +49 -3
- package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +55 -0
- package/Types/OnCallDutyPolicy/Layer.ts +203 -149
- package/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.ts +13 -0
- package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +155 -10
- package/Types/Permission.ts +193 -0
- package/Types/Telemetry/EntityRelationshipType.ts +1 -1
- package/Types/Telemetry/EntitySource.ts +1 -1
- package/Types/Telemetry/EntityType.ts +1 -1
- package/Types/Telemetry/EntityTypeGroups.ts +1 -1
- package/Types/Workflow/Components/BaseModel.ts +75 -29
- package/Types/Workflow/Components/Discord.ts +1 -0
- package/Types/Workflow/Components/Email.ts +12 -3
- package/Types/Workflow/Components/JavaScript.ts +7 -0
- package/Types/Workflow/Components/MicrosoftTeams.ts +3 -2
- package/Types/Workflow/Components/Slack.ts +1 -0
- package/Types/Workflow/Components/Telegram.ts +1 -0
- package/Types/Workflow/TemplateSyntax.ts +44 -0
- package/Types/Workflow/Templates.ts +2097 -45
- package/UI/Components/Calendar/Calendar.css +43 -0
- package/UI/Components/Calendar/Calendar.tsx +8 -0
- package/UI/Components/Card/Card.tsx +2 -2
- package/UI/Components/Checkbox/Checkbox.tsx +16 -0
- package/UI/Components/Dictionary/Dictionary.tsx +48 -9
- package/UI/Components/FormModal/BasicFormModal.tsx +2 -1
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +53 -3
- package/UI/Components/Input/Input.tsx +1 -0
- package/UI/Components/KeyboardShortcut/KeyboardKey.ts +185 -0
- package/UI/Components/KeyboardShortcut/KeyboardShortcut.tsx +87 -0
- package/UI/Components/LogsViewer/LogsViewer.tsx +28 -0
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +31 -0
- package/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.tsx +18 -18
- package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +363 -14
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +11 -0
- package/UI/Components/LogsViewer/components/LogsTable.tsx +155 -12
- package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +29 -0
- package/UI/Components/LogsViewer/types.ts +23 -0
- package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +9 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +15 -30
- package/UI/Components/ProjectInvitations/PendingProjectInvitations.tsx +442 -0
- package/UI/Components/SimpleLogViewer/SimpleLogViewer.tsx +23 -1
- package/UI/Components/Table/Table.tsx +49 -16
- package/UI/Components/Table/TableBody.tsx +53 -28
- package/UI/Components/Table/TableHeader.tsx +13 -0
- package/UI/Components/Table/TableRow.tsx +58 -26
- package/UI/Components/Workflow/ArgumentsForm.tsx +155 -9
- package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +26 -0
- package/UI/Components/Workflow/ComponentSettingsModal.tsx +10 -1
- package/UI/Components/Workflow/ComponentValuePickerModal.tsx +135 -7
- package/UI/Components/Workflow/ComponentsModal.tsx +116 -22
- package/UI/Components/Workflow/DocumentationViewer.tsx +59 -9
- package/UI/Components/Workflow/GraphLint.ts +42 -5
- package/UI/Components/Workflow/GraphLintSummary.ts +390 -0
- package/UI/Components/Workflow/ModelColumnEditor.tsx +154 -22
- package/UI/Components/Workflow/ModelSchema.ts +115 -33
- package/UI/Components/Workflow/RunStatusWatcher.ts +1 -1
- package/UI/Components/Workflow/StepTraceViewer.tsx +1 -1
- package/UI/Components/Workflow/UseRunWatch.ts +212 -0
- package/UI/Components/Workflow/VariableModal.tsx +6 -2
- package/UI/Components/Workflow/Workflow.tsx +49 -3
- package/UI/Components/Workflow/WorkflowIssuesModal.tsx +255 -0
- package/UI/Components/Workflow/WorkflowLogModal.tsx +128 -0
- package/UI/Components/Workflow/WorkflowStatusBar.tsx +224 -0
- package/UI/Utils/AIChatExport/ConversationMarkdown.ts +10 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +7 -1
- package/UI/Utils/Platform.ts +149 -0
- package/UI/Utils/ProjectInvitationDisplay.ts +118 -0
- package/UI/esbuild-config.js +22 -1
- package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +187 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +888 -164
- package/Utils/Telemetry/CrossSignalScope.ts +502 -0
- package/Utils/Telemetry/EntityKey.ts +5 -5
- package/Utils/Telemetry/EntityRelationship.ts +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +1 -1
- package/build/dist/Models/DatabaseModels/AIConversation.js +32 -0
- package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AIConversationMessage.js +42 -0
- package/build/dist/Models/DatabaseModels/AIConversationMessage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +28 -0
- package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +29 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +12 -4
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/{TelemetryEntity.js → InventoryItem.js} +167 -31
- package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -0
- package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js +454 -0
- package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js.map +1 -0
- package/build/dist/Models/DatabaseModels/{TelemetryEntityRelationship.js → InventoryItemRelationship.js} +27 -27
- package/build/dist/Models/DatabaseModels/InventoryItemRelationship.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +141 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js +719 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +475 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js +446 -0
- package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js.map +1 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js +9 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +80 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserCall.js +46 -2
- package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserEmail.js +48 -2
- package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationRule.js +424 -55
- package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +24 -2
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserPush.js +51 -1
- package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserSMS.js +47 -2
- package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserTelegram.js +65 -3
- package/build/dist/Models/DatabaseModels/UserTelegram.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebhook.js +56 -2
- package/build/dist/Models/DatabaseModels/UserWebhook.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js +45 -2
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js +12 -0
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +237 -1
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +165 -13
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallReadinessAPI.js +599 -0
- package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -0
- package/build/dist/Server/API/TeamComplianceAPI.js +68 -9
- package/build/dist/Server/API/TeamComplianceAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +129 -18
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +45 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js +4 -4
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js +39 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js +38 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js +150 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js +57 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js +69 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js +32 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js +48 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Queue.js +72 -13
- package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
- package/build/dist/Server/Middleware/PublicDashboardRateLimit.js +399 -0
- package/build/dist/Server/Middleware/PublicDashboardRateLimit.js.map +1 -0
- package/build/dist/Server/Services/AIService.js +1 -0
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js +24 -3
- package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/AlertSeverityService.js +54 -0
- package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
- package/build/dist/Server/Services/DashboardService.js +10 -9
- package/build/dist/Server/Services/DashboardService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +24 -2
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +24 -3
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSeverityService.js +67 -0
- package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +12 -4
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemCustomFieldService.js +9 -0
- package/build/dist/Server/Services/InventoryItemCustomFieldService.js.map +1 -0
- package/build/dist/Server/Services/{TelemetryEntityRelationshipService.js → InventoryItemRelationshipService.js} +6 -6
- package/build/dist/Server/Services/InventoryItemRelationshipService.js.map +1 -0
- package/build/dist/Server/Services/{TelemetryEntityService.js → InventoryItemService.js} +68 -23
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -0
- package/build/dist/Server/Services/LogAggregationService.js +27 -8
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +80 -0
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricService.js +6 -6
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js +9 -0
- package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceLinkService.js +71 -0
- package/build/dist/Server/Services/NetworkDeviceLinkService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceService.js +113 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +53 -13
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkTopologySuppressionService.js +85 -0
- package/build/dist/Server/Services/NetworkTopologySuppressionService.js.map +1 -0
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +48 -32
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +8 -0
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +51 -12
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +57 -13
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallNotificationAlertingService.js +548 -0
- package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -0
- package/build/dist/Server/Services/OnCallReadinessService.js +1961 -0
- package/build/dist/Server/Services/OnCallReadinessService.js.map +1 -0
- package/build/dist/Server/Services/OnCallSetupReminderService.js +738 -0
- package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -0
- package/build/dist/Server/Services/ProfileAggregationService.js +68 -4
- package/build/dist/Server/Services/ProfileAggregationService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +11 -10
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceService.js +312 -160
- package/build/dist/Server/Services/TeamComplianceService.js.map +1 -1
- package/build/dist/Server/Services/UserCallService.js +24 -1
- package/build/dist/Server/Services/UserCallService.js.map +1 -1
- package/build/dist/Server/Services/UserEmailService.js +24 -1
- package/build/dist/Server/Services/UserEmailService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleAdminService.js +858 -0
- package/build/dist/Server/Services/UserNotificationRuleAdminService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js +2830 -175
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserOnCallLogService.js +488 -43
- package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
- package/build/dist/Server/Services/UserPushService.js +26 -0
- package/build/dist/Server/Services/UserPushService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +10 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/UserSmsService.js +24 -1
- package/build/dist/Server/Services/UserSmsService.js.map +1 -1
- package/build/dist/Server/Services/UserTelegramService.js +22 -1
- package/build/dist/Server/Services/UserTelegramService.js.map +1 -1
- package/build/dist/Server/Services/UserWebhookService.js +25 -1
- package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
- package/build/dist/Server/Services/UserWhatsAppService.js +22 -1
- package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js +12 -1
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +126 -0
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js +254 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js.map +1 -0
- package/build/dist/Server/Types/Database/Permissions/QueryPermission.js +47 -2
- package/build/dist/Server/Types/Database/Permissions/QueryPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +7 -0
- package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +21 -5
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +14 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +31 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js +3 -9
- package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Email.js +15 -4
- package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js +7 -2
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +514 -56
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +20 -3
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +19 -6
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +7 -0
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js +2 -2
- package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js +692 -0
- package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +148 -12
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +157 -10
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +37 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js +259 -14
- package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js +235 -0
- package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +1000 -0
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js +356 -0
- package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +394 -0
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js +465 -0
- package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js +280 -0
- package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js +527 -0
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js +548 -0
- package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js.map +1 -0
- package/build/dist/Server/Utils/ClientIp.js +137 -0
- package/build/dist/Server/Utils/ClientIp.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +38 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js +89 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js +77 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js.map +1 -0
- package/build/dist/Server/Utils/Express.js +12 -12
- package/build/dist/Server/Utils/Express.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +70 -7
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +121 -11
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +82 -21
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +12 -4
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +165 -18
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +11 -11
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +122 -47
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +7 -3
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/AI/AIChatMessageStatus.js +8 -1
- package/build/dist/Types/AI/AIChatMessageStatus.js.map +1 -1
- package/build/dist/Types/AI/AIChatTypes.js +12 -0
- package/build/dist/Types/AI/AIChatTypes.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +60 -0
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -0
- package/build/dist/Types/Exception/ExceptionCode.js +2 -0
- package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
- package/build/dist/Types/Exception/ServiceUnavailableException.js +8 -0
- package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js +8 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -0
- package/build/dist/Types/IP/IP.js +87 -43
- package/build/dist/Types/IP/IP.js.map +1 -1
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +50 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +186 -123
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js +13 -0
- package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +105 -11
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
- package/build/dist/Types/Permission.js +174 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityRelationshipType.js +1 -1
- package/build/dist/Types/Telemetry/EntitySource.js +1 -1
- package/build/dist/Types/Telemetry/EntityType.js +1 -1
- package/build/dist/Types/Telemetry/EntityTypeGroups.js +1 -1
- package/build/dist/Types/Telemetry/EntityTypeGroups.js.map +1 -1
- package/build/dist/Types/Workflow/Components/BaseModel.js +66 -28
- package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Discord.js +1 -0
- package/build/dist/Types/Workflow/Components/Discord.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Email.js +12 -3
- package/build/dist/Types/Workflow/Components/Email.js.map +1 -1
- package/build/dist/Types/Workflow/Components/JavaScript.js +7 -0
- package/build/dist/Types/Workflow/Components/JavaScript.js.map +1 -1
- package/build/dist/Types/Workflow/Components/MicrosoftTeams.js +3 -2
- package/build/dist/Types/Workflow/Components/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Slack.js +1 -0
- package/build/dist/Types/Workflow/Components/Slack.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Telegram.js +1 -0
- package/build/dist/Types/Workflow/Components/Telegram.js.map +1 -1
- package/build/dist/Types/Workflow/TemplateSyntax.js +12 -0
- package/build/dist/Types/Workflow/TemplateSyntax.js.map +1 -1
- package/build/dist/Types/Workflow/Templates.js +1931 -38
- package/build/dist/Types/Workflow/Templates.js.map +1 -1
- package/build/dist/UI/Components/Calendar/Calendar.js +1 -1
- package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
- package/build/dist/UI/Components/Checkbox/Checkbox.js +1 -1
- package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
- package/build/dist/UI/Components/Dictionary/Dictionary.js +25 -11
- package/build/dist/UI/Components/Dictionary/Dictionary.js.map +1 -1
- package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +27 -4
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +1 -0
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js +163 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js.map +1 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js +47 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +4 -4
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +11 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js +10 -8
- package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +227 -14
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +5 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +69 -5
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +8 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +9 -2
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +8 -21
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js +251 -0
- package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js.map +1 -0
- package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js +9 -2
- package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +27 -15
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableBody.js +24 -18
- package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
- package/build/dist/UI/Components/Table/TableHeader.js +9 -1
- package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +29 -21
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +130 -12
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +10 -1
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +4 -4
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js +57 -7
- package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +53 -18
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/DocumentationViewer.js +19 -6
- package/build/dist/UI/Components/Workflow/DocumentationViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/GraphLint.js +33 -4
- package/build/dist/UI/Components/Workflow/GraphLint.js.map +1 -1
- package/build/dist/UI/Components/Workflow/GraphLintSummary.js +231 -0
- package/build/dist/UI/Components/Workflow/GraphLintSummary.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js +116 -21
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ModelSchema.js +72 -34
- package/build/dist/UI/Components/Workflow/ModelSchema.js.map +1 -1
- package/build/dist/UI/Components/Workflow/RunStatusWatcher.js +1 -1
- package/build/dist/UI/Components/Workflow/RunStatusWatcher.js.map +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/UseRunWatch.js +123 -0
- package/build/dist/UI/Components/Workflow/UseRunWatch.js.map +1 -0
- package/build/dist/UI/Components/Workflow/VariableModal.js +3 -2
- package/build/dist/UI/Components/Workflow/VariableModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Workflow.js +41 -1
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js +99 -0
- package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js.map +1 -0
- package/build/dist/UI/Components/Workflow/WorkflowLogModal.js +56 -0
- package/build/dist/UI/Components/Workflow/WorkflowLogModal.js.map +1 -0
- package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js +92 -0
- package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js.map +1 -0
- package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js +9 -0
- package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/Platform.js +118 -0
- package/build/dist/UI/Utils/Platform.js.map +1 -0
- package/build/dist/UI/Utils/ProjectInvitationDisplay.js +106 -0
- package/build/dist/UI/Utils/ProjectInvitationDisplay.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +108 -0
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +642 -136
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +328 -0
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +5 -5
- package/build/dist/Utils/Telemetry/EntityRelationship.js +1 -1
- package/jest.config.json +1 -0
- package/package.json +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntity.js.map +0 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js.map +0 -1
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +0 -1
- package/build/dist/Server/Services/TelemetryEntityService.js.map +0 -1
|
@@ -0,0 +1,1312 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import NotificationRuleType from "../../../Types/NotificationRule/NotificationRuleType";
|
|
3
|
+
import {
|
|
4
|
+
CustomFieldProbe,
|
|
5
|
+
DeliverableSettingsProbe,
|
|
6
|
+
IncomingCallProbe,
|
|
7
|
+
OnCallShiftAlertProbe,
|
|
8
|
+
SetupChecklist,
|
|
9
|
+
SetupChecklistInput,
|
|
10
|
+
SetupHeadlineStatus,
|
|
11
|
+
SetupSection,
|
|
12
|
+
SetupStep,
|
|
13
|
+
SetupStepImportance,
|
|
14
|
+
SetupStepStatus,
|
|
15
|
+
WorkspaceProbe,
|
|
16
|
+
buildSetupChecklist,
|
|
17
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Components/UserSettings/SetupChecklist/ChecklistModel";
|
|
18
|
+
import PageMap from "../../../../App/FeatureSet/Dashboard/src/Utils/PageMap";
|
|
19
|
+
import {
|
|
20
|
+
ReadinessCoverageCellWire,
|
|
21
|
+
ReadinessMethodWire,
|
|
22
|
+
ReadinessStatusValue,
|
|
23
|
+
ResponderSourceValue,
|
|
24
|
+
UserReadinessWire,
|
|
25
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Components/OnCallPolicy/Readiness/ReadinessTypes";
|
|
26
|
+
|
|
27
|
+
/*
|
|
28
|
+
* WHAT THIS FILE STANDS GUARD OVER.
|
|
29
|
+
*
|
|
30
|
+
* The checklist's whole value is that it tells somebody the truth about their
|
|
31
|
+
* own notification setup. Every way it could lie is cheap to introduce and
|
|
32
|
+
* expensive to notice in production, because the reader has no second source -
|
|
33
|
+
* if the page says "Done", they stop looking. The failures below are the ones
|
|
34
|
+
* that would produce a page that looks fine and is wrong:
|
|
35
|
+
*
|
|
36
|
+
* - crediting work that does not exist. A project with no alert severities
|
|
37
|
+
* has no alert cells, and counting "no gaps" as "you set this up" both
|
|
38
|
+
* flatters the reader and hides the moment an admin adds the first
|
|
39
|
+
* severity and the step silently becomes a real gap.
|
|
40
|
+
* - counting a step the reader cannot do. A verified method on a channel the
|
|
41
|
+
* project switched off is not their failure and not their fix; a progress
|
|
42
|
+
* bar that can never reach the end is a progress bar people stop reading.
|
|
43
|
+
* - turning "we could not check" into "you have not done it". Every probe can
|
|
44
|
+
* fail independently, and an unknown probe must produce NO step rather than
|
|
45
|
+
* a task the reader cannot complete because it was never real.
|
|
46
|
+
* - stating a consequence without knowing the fallback switch. "Those pages
|
|
47
|
+
* still reach you" and "those pages are dropped" are both plausible
|
|
48
|
+
* sentences and only one is true; guessing the reassuring one costs a page.
|
|
49
|
+
* - letting optional work mask required work. Connecting Slack must never
|
|
50
|
+
* move somebody towards "ready" while nothing can page them.
|
|
51
|
+
*
|
|
52
|
+
* The model is pure, so all of this is testable without a browser, a server or
|
|
53
|
+
* a clock - which is the reason it was written as a separate module at all.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
const SEVERITY_ONE: string = "11111111-1111-4111-8111-111111111111";
|
|
57
|
+
const SEVERITY_TWO: string = "22222222-2222-4222-8222-222222222222";
|
|
58
|
+
const SEVERITY_THREE: string = "33333333-3333-4333-8333-333333333333";
|
|
59
|
+
const SEVERITY_FOUR: string = "44444444-4444-4444-8444-444444444444";
|
|
60
|
+
|
|
61
|
+
type MakeCellFunction = (params: {
|
|
62
|
+
ruleType: NotificationRuleType;
|
|
63
|
+
severityId: string;
|
|
64
|
+
severityName: string;
|
|
65
|
+
hasRule?: boolean | undefined;
|
|
66
|
+
isOptOut?: boolean | undefined;
|
|
67
|
+
}) => ReadinessCoverageCellWire;
|
|
68
|
+
|
|
69
|
+
const makeCell: MakeCellFunction = (params: {
|
|
70
|
+
ruleType: NotificationRuleType;
|
|
71
|
+
severityId: string;
|
|
72
|
+
severityName: string;
|
|
73
|
+
hasRule?: boolean | undefined;
|
|
74
|
+
isOptOut?: boolean | undefined;
|
|
75
|
+
}): ReadinessCoverageCellWire => {
|
|
76
|
+
return {
|
|
77
|
+
ruleType: params.ruleType,
|
|
78
|
+
severityId: params.severityId,
|
|
79
|
+
severityName: params.severityName,
|
|
80
|
+
hasRule: params.hasRule ?? true,
|
|
81
|
+
isOptOut: params.isOptOut ?? false,
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
type MakeMethodFunction = (
|
|
86
|
+
methodType: string,
|
|
87
|
+
isVerified: boolean,
|
|
88
|
+
) => ReadinessMethodWire;
|
|
89
|
+
|
|
90
|
+
const makeMethod: MakeMethodFunction = (
|
|
91
|
+
methodType: string,
|
|
92
|
+
isVerified: boolean,
|
|
93
|
+
): ReadinessMethodWire => {
|
|
94
|
+
return {
|
|
95
|
+
methodId: `method-${methodType}`,
|
|
96
|
+
methodType: methodType,
|
|
97
|
+
maskedIdentifier: "•••",
|
|
98
|
+
isVerified: isVerified,
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/*
|
|
103
|
+
* Full coverage across all four rule types and two severities of each kind.
|
|
104
|
+
* Tests that want a gap punch a hole in this rather than building a payload
|
|
105
|
+
* from nothing, so the thing under test is the hole and not the fixture.
|
|
106
|
+
*/
|
|
107
|
+
type FullCoverageFunction = () => Array<ReadinessCoverageCellWire>;
|
|
108
|
+
|
|
109
|
+
const fullCoverage: FullCoverageFunction =
|
|
110
|
+
(): Array<ReadinessCoverageCellWire> => {
|
|
111
|
+
return [
|
|
112
|
+
makeCell({
|
|
113
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
114
|
+
severityId: SEVERITY_ONE,
|
|
115
|
+
severityName: "Sev1",
|
|
116
|
+
}),
|
|
117
|
+
makeCell({
|
|
118
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
119
|
+
severityId: SEVERITY_TWO,
|
|
120
|
+
severityName: "Sev2",
|
|
121
|
+
}),
|
|
122
|
+
makeCell({
|
|
123
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
124
|
+
severityId: SEVERITY_ONE,
|
|
125
|
+
severityName: "Sev1",
|
|
126
|
+
}),
|
|
127
|
+
makeCell({
|
|
128
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
129
|
+
severityId: SEVERITY_TWO,
|
|
130
|
+
severityName: "Sev2",
|
|
131
|
+
}),
|
|
132
|
+
makeCell({
|
|
133
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_ALERT,
|
|
134
|
+
severityId: SEVERITY_THREE,
|
|
135
|
+
severityName: "Warning",
|
|
136
|
+
}),
|
|
137
|
+
makeCell({
|
|
138
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_ALERT,
|
|
139
|
+
severityId: SEVERITY_FOUR,
|
|
140
|
+
severityName: "Critical",
|
|
141
|
+
}),
|
|
142
|
+
makeCell({
|
|
143
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE,
|
|
144
|
+
severityId: SEVERITY_THREE,
|
|
145
|
+
severityName: "Warning",
|
|
146
|
+
}),
|
|
147
|
+
makeCell({
|
|
148
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE,
|
|
149
|
+
severityId: SEVERITY_FOUR,
|
|
150
|
+
severityName: "Critical",
|
|
151
|
+
}),
|
|
152
|
+
];
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
type MakeReadinessFunction = (params?: {
|
|
156
|
+
status?: ReadinessStatusValue | undefined;
|
|
157
|
+
methods?: Array<ReadinessMethodWire> | undefined;
|
|
158
|
+
coverage?: Array<ReadinessCoverageCellWire> | undefined;
|
|
159
|
+
reachedVia?: Array<ResponderSourceValue> | undefined;
|
|
160
|
+
}) => UserReadinessWire;
|
|
161
|
+
|
|
162
|
+
const makeReadiness: MakeReadinessFunction = (params?: {
|
|
163
|
+
status?: ReadinessStatusValue | undefined;
|
|
164
|
+
methods?: Array<ReadinessMethodWire> | undefined;
|
|
165
|
+
coverage?: Array<ReadinessCoverageCellWire> | undefined;
|
|
166
|
+
reachedVia?: Array<ResponderSourceValue> | undefined;
|
|
167
|
+
}): UserReadinessWire => {
|
|
168
|
+
return {
|
|
169
|
+
userId: "99999999-9999-4999-8999-999999999999",
|
|
170
|
+
userName: "Ada Lovelace",
|
|
171
|
+
userEmail: "ada@example.com",
|
|
172
|
+
status: params?.status ?? "Ready",
|
|
173
|
+
methods: params?.methods ?? [makeMethod("Email", true)],
|
|
174
|
+
coverage: params?.coverage ?? fullCoverage(),
|
|
175
|
+
reasons: [],
|
|
176
|
+
reachedVia: params?.reachedVia ?? ["Team"],
|
|
177
|
+
/*
|
|
178
|
+
* The teams that page this responder. Empty here because nothing in this
|
|
179
|
+
* checklist reads them - it asks whether the signed-in user's own setup is
|
|
180
|
+
* complete, not which door pages reach them through.
|
|
181
|
+
*/
|
|
182
|
+
teams: [],
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const KNOWN_SHIFT_ALERTS: OnCallShiftAlertProbe = {
|
|
187
|
+
isKnown: true,
|
|
188
|
+
hasAnyChannelEnabled: true,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const KNOWN_DELIVERABLE: DeliverableSettingsProbe = {
|
|
192
|
+
isKnown: true,
|
|
193
|
+
undeliverableChannels: [],
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const KNOWN_NO_INCOMING_CALL: IncomingCallProbe = {
|
|
197
|
+
isKnown: true,
|
|
198
|
+
hasPolicyInProject: false,
|
|
199
|
+
hasVerifiedNumber: false,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const KNOWN_NO_WORKSPACE: WorkspaceProbe = {
|
|
203
|
+
isKnown: true,
|
|
204
|
+
isConnectedForProject: false,
|
|
205
|
+
isConnectedForUser: false,
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const KNOWN_NO_CUSTOM_FIELDS: CustomFieldProbe = {
|
|
209
|
+
isKnown: true,
|
|
210
|
+
fieldCount: 0,
|
|
211
|
+
filledFieldCount: 0,
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
type MakeInputFunction = (
|
|
215
|
+
overrides?: Partial<SetupChecklistInput> | undefined,
|
|
216
|
+
) => SetupChecklistInput;
|
|
217
|
+
|
|
218
|
+
const makeInput: MakeInputFunction = (
|
|
219
|
+
overrides?: Partial<SetupChecklistInput> | undefined,
|
|
220
|
+
): SetupChecklistInput => {
|
|
221
|
+
return {
|
|
222
|
+
readiness: makeReadiness(),
|
|
223
|
+
isFallbackEnabled: true,
|
|
224
|
+
isFallbackKnown: true,
|
|
225
|
+
onCallShiftAlerts: KNOWN_SHIFT_ALERTS,
|
|
226
|
+
deliverableSettings: KNOWN_DELIVERABLE,
|
|
227
|
+
incomingCall: KNOWN_NO_INCOMING_CALL,
|
|
228
|
+
slack: KNOWN_NO_WORKSPACE,
|
|
229
|
+
microsoftTeams: KNOWN_NO_WORKSPACE,
|
|
230
|
+
customFields: KNOWN_NO_CUSTOM_FIELDS,
|
|
231
|
+
...overrides,
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
type AllStepsFunction = (checklist: SetupChecklist) => Array<SetupStep>;
|
|
236
|
+
|
|
237
|
+
const allSteps: AllStepsFunction = (
|
|
238
|
+
checklist: SetupChecklist,
|
|
239
|
+
): Array<SetupStep> => {
|
|
240
|
+
return checklist.sections.flatMap(
|
|
241
|
+
(section: SetupSection): Array<SetupStep> => {
|
|
242
|
+
return section.steps;
|
|
243
|
+
},
|
|
244
|
+
);
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
type FindStepFunction = (
|
|
248
|
+
checklist: SetupChecklist,
|
|
249
|
+
key: string,
|
|
250
|
+
) => SetupStep | undefined;
|
|
251
|
+
|
|
252
|
+
const findStep: FindStepFunction = (
|
|
253
|
+
checklist: SetupChecklist,
|
|
254
|
+
key: string,
|
|
255
|
+
): SetupStep | undefined => {
|
|
256
|
+
return allSteps(checklist).find((step: SetupStep): boolean => {
|
|
257
|
+
return step.key === key;
|
|
258
|
+
});
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
type StepKeysFunction = (checklist: SetupChecklist) => Array<string>;
|
|
262
|
+
|
|
263
|
+
const stepKeys: StepKeysFunction = (
|
|
264
|
+
checklist: SetupChecklist,
|
|
265
|
+
): Array<string> => {
|
|
266
|
+
return allSteps(checklist).map((step: SetupStep): string => {
|
|
267
|
+
return step.key;
|
|
268
|
+
});
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
describe("setup checklist - reaching you at all", () => {
|
|
272
|
+
test("asks for a notification method when the user has none", () => {
|
|
273
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
274
|
+
makeInput({
|
|
275
|
+
readiness: makeReadiness({
|
|
276
|
+
status: "NotReachable",
|
|
277
|
+
methods: [],
|
|
278
|
+
}),
|
|
279
|
+
}),
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
const step: SetupStep | undefined = findStep(checklist, "add-method");
|
|
283
|
+
|
|
284
|
+
expect(step).toBeDefined();
|
|
285
|
+
expect(step!.status).toBe(SetupStepStatus.Incomplete);
|
|
286
|
+
expect(step!.importance).toBe(SetupStepImportance.Required);
|
|
287
|
+
expect(step!.pageMap).toBe(PageMap.USER_SETTINGS_NOTIFICATION_METHODS);
|
|
288
|
+
expect(step!.detail).toBe(
|
|
289
|
+
"You have no notification methods on this project.",
|
|
290
|
+
);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
/*
|
|
294
|
+
* "Add a method" and "verify your methods" are one action for somebody with
|
|
295
|
+
* nothing at all. Showing both makes the list look twice as long as the work
|
|
296
|
+
* and puts a task on screen that cannot be started.
|
|
297
|
+
*/
|
|
298
|
+
test("does not ask to verify methods when there are no methods to verify", () => {
|
|
299
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
300
|
+
makeInput({
|
|
301
|
+
readiness: makeReadiness({
|
|
302
|
+
status: "NotReachable",
|
|
303
|
+
methods: [],
|
|
304
|
+
}),
|
|
305
|
+
}),
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
expect(stepKeys(checklist)).not.toContain("verify-methods");
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test("asks to verify once a method exists but is unverified", () => {
|
|
312
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
313
|
+
makeInput({
|
|
314
|
+
readiness: makeReadiness({
|
|
315
|
+
status: "NotReachable",
|
|
316
|
+
methods: [makeMethod("SMS", false)],
|
|
317
|
+
}),
|
|
318
|
+
}),
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
const addStep: SetupStep | undefined = findStep(checklist, "add-method");
|
|
322
|
+
const verifyStep: SetupStep | undefined = findStep(
|
|
323
|
+
checklist,
|
|
324
|
+
"verify-methods",
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
expect(addStep!.status).toBe(SetupStepStatus.Complete);
|
|
328
|
+
expect(verifyStep!.status).toBe(SetupStepStatus.Incomplete);
|
|
329
|
+
expect(verifyStep!.detail).toBe(
|
|
330
|
+
"1 method is still waiting to be verified.",
|
|
331
|
+
);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
test("counts several unverified methods in the plural", () => {
|
|
335
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
336
|
+
makeInput({
|
|
337
|
+
readiness: makeReadiness({
|
|
338
|
+
status: "PartiallyReady",
|
|
339
|
+
methods: [
|
|
340
|
+
makeMethod("Email", true),
|
|
341
|
+
makeMethod("SMS", false),
|
|
342
|
+
makeMethod("Call", false),
|
|
343
|
+
],
|
|
344
|
+
}),
|
|
345
|
+
}),
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
expect(findStep(checklist, "verify-methods")!.detail).toBe(
|
|
349
|
+
"2 methods are still waiting to be verified.",
|
|
350
|
+
);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
/*
|
|
354
|
+
* The trap this whole step exists for. All four paid channels default to OFF
|
|
355
|
+
* on a project, so somebody who verifies only SMS sees a green tick on their
|
|
356
|
+
* methods page and is reported NotReachable - and the fix is an admin's, not
|
|
357
|
+
* theirs.
|
|
358
|
+
*/
|
|
359
|
+
test("marks a verified-but-switched-off channel as blocked, with no link", () => {
|
|
360
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
361
|
+
makeInput({
|
|
362
|
+
readiness: makeReadiness({
|
|
363
|
+
status: "NotReachable",
|
|
364
|
+
methods: [makeMethod("SMS", true)],
|
|
365
|
+
}),
|
|
366
|
+
}),
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
const step: SetupStep | undefined = findStep(checklist, "channels-enabled");
|
|
370
|
+
|
|
371
|
+
expect(step!.status).toBe(SetupStepStatus.Blocked);
|
|
372
|
+
expect(step!.pageMap).toBeUndefined();
|
|
373
|
+
expect(step!.actionTitle).toBe(
|
|
374
|
+
"Ask a project admin to enable this channel",
|
|
375
|
+
);
|
|
376
|
+
expect(step!.detail).toContain("Ask a project admin to enable it");
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
/*
|
|
380
|
+
* The number that reconciles a full progress bar with a red headline. Without
|
|
381
|
+
* it somebody whose only verified method is on a switched-off channel reads
|
|
382
|
+
* "N of N essential steps done" directly under "Nothing can reach you yet".
|
|
383
|
+
*/
|
|
384
|
+
test("reports blocked steps separately from the progress counts", () => {
|
|
385
|
+
const blocked: SetupChecklist = buildSetupChecklist(
|
|
386
|
+
makeInput({
|
|
387
|
+
readiness: makeReadiness({
|
|
388
|
+
status: "NotReachable",
|
|
389
|
+
methods: [makeMethod("SMS", true)],
|
|
390
|
+
}),
|
|
391
|
+
}),
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
expect(blocked.blockedCount).toBe(1);
|
|
395
|
+
expect(blocked.completedCount).toBe(blocked.totalCount);
|
|
396
|
+
expect(blocked.headlineStatus).toBe(SetupHeadlineStatus.NotReachable);
|
|
397
|
+
|
|
398
|
+
const healthy: SetupChecklist = buildSetupChecklist(makeInput());
|
|
399
|
+
|
|
400
|
+
expect(healthy.blockedCount).toBe(0);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
test("a blocked channel step is not counted towards progress", () => {
|
|
404
|
+
const blocked: SetupChecklist = buildSetupChecklist(
|
|
405
|
+
makeInput({
|
|
406
|
+
readiness: makeReadiness({
|
|
407
|
+
status: "NotReachable",
|
|
408
|
+
methods: [makeMethod("SMS", true)],
|
|
409
|
+
}),
|
|
410
|
+
}),
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
const counted: Array<SetupStep> = allSteps(blocked).filter(
|
|
414
|
+
(step: SetupStep): boolean => {
|
|
415
|
+
return (
|
|
416
|
+
step.importance !== SetupStepImportance.Optional &&
|
|
417
|
+
(step.status === SetupStepStatus.Complete ||
|
|
418
|
+
step.status === SetupStepStatus.Incomplete)
|
|
419
|
+
);
|
|
420
|
+
},
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
expect(blocked.totalCount).toBe(counted.length);
|
|
424
|
+
expect(
|
|
425
|
+
counted.some((step: SetupStep): boolean => {
|
|
426
|
+
return step.key === "channels-enabled";
|
|
427
|
+
}),
|
|
428
|
+
).toBe(false);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
test("the channel step is complete, and links onward, when nothing is switched off", () => {
|
|
432
|
+
const checklist: SetupChecklist = buildSetupChecklist(makeInput());
|
|
433
|
+
const step: SetupStep | undefined = findStep(checklist, "channels-enabled");
|
|
434
|
+
|
|
435
|
+
expect(step!.status).toBe(SetupStepStatus.Complete);
|
|
436
|
+
expect(step!.pageMap).toBe(PageMap.USER_SETTINGS_NOTIFICATION_METHODS);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
/*
|
|
440
|
+
* A user whose only method is an unverified one has nothing usable, so there
|
|
441
|
+
* is no channel to be switched off yet and the step would be asking about
|
|
442
|
+
* something that does not exist.
|
|
443
|
+
*/
|
|
444
|
+
test("omits the channel step entirely when no method is verified", () => {
|
|
445
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
446
|
+
makeInput({
|
|
447
|
+
readiness: makeReadiness({
|
|
448
|
+
status: "NotReachable",
|
|
449
|
+
methods: [makeMethod("Email", false)],
|
|
450
|
+
}),
|
|
451
|
+
}),
|
|
452
|
+
);
|
|
453
|
+
|
|
454
|
+
expect(stepKeys(checklist)).not.toContain("channels-enabled");
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
describe("setup checklist - paging rules", () => {
|
|
459
|
+
test("one step per rule type, each pointing at its own page", () => {
|
|
460
|
+
const checklist: SetupChecklist = buildSetupChecklist(makeInput());
|
|
461
|
+
|
|
462
|
+
expect(findStep(checklist, "incident-rules")!.pageMap).toBe(
|
|
463
|
+
PageMap.USER_SETTINGS_INCIDENT_ON_CALL_RULES,
|
|
464
|
+
);
|
|
465
|
+
expect(findStep(checklist, "incident-episode-rules")!.pageMap).toBe(
|
|
466
|
+
PageMap.USER_SETTINGS_INCIDENT_EPISODE_ON_CALL_RULES,
|
|
467
|
+
);
|
|
468
|
+
expect(findStep(checklist, "alert-rules")!.pageMap).toBe(
|
|
469
|
+
PageMap.USER_SETTINGS_ALERT_ON_CALL_RULES,
|
|
470
|
+
);
|
|
471
|
+
expect(findStep(checklist, "alert-episode-rules")!.pageMap).toBe(
|
|
472
|
+
PageMap.USER_SETTINGS_ALERT_EPISODE_ON_CALL_RULES,
|
|
473
|
+
);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
test("a rule type with full coverage is complete and says nothing more", () => {
|
|
477
|
+
const checklist: SetupChecklist = buildSetupChecklist(makeInput());
|
|
478
|
+
const step: SetupStep | undefined = findStep(checklist, "incident-rules");
|
|
479
|
+
|
|
480
|
+
expect(step!.status).toBe(SetupStepStatus.Complete);
|
|
481
|
+
expect(step!.detail).toBe("");
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
test("names the severities that have no rule", () => {
|
|
485
|
+
const coverage: Array<ReadinessCoverageCellWire> = fullCoverage().map(
|
|
486
|
+
(cell: ReadinessCoverageCellWire): ReadinessCoverageCellWire => {
|
|
487
|
+
if (
|
|
488
|
+
cell.ruleType === NotificationRuleType.ON_CALL_EXECUTED_INCIDENT &&
|
|
489
|
+
cell.severityName === "Sev2"
|
|
490
|
+
) {
|
|
491
|
+
return { ...cell, hasRule: false };
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return cell;
|
|
495
|
+
},
|
|
496
|
+
);
|
|
497
|
+
|
|
498
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
499
|
+
makeInput({
|
|
500
|
+
readiness: makeReadiness({
|
|
501
|
+
status: "PartiallyReady",
|
|
502
|
+
coverage: coverage,
|
|
503
|
+
}),
|
|
504
|
+
}),
|
|
505
|
+
);
|
|
506
|
+
|
|
507
|
+
const step: SetupStep | undefined = findStep(checklist, "incident-rules");
|
|
508
|
+
|
|
509
|
+
expect(step!.status).toBe(SetupStepStatus.Incomplete);
|
|
510
|
+
expect(step!.detail).toBe("Sev2 has no rule.");
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
test("joins two missing severities with 'and', and uses the plural verb", () => {
|
|
514
|
+
const coverage: Array<ReadinessCoverageCellWire> = fullCoverage().map(
|
|
515
|
+
(cell: ReadinessCoverageCellWire): ReadinessCoverageCellWire => {
|
|
516
|
+
if (cell.ruleType === NotificationRuleType.ON_CALL_EXECUTED_ALERT) {
|
|
517
|
+
return { ...cell, hasRule: false };
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
return cell;
|
|
521
|
+
},
|
|
522
|
+
);
|
|
523
|
+
|
|
524
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
525
|
+
makeInput({
|
|
526
|
+
readiness: makeReadiness({
|
|
527
|
+
status: "PartiallyReady",
|
|
528
|
+
coverage: coverage,
|
|
529
|
+
}),
|
|
530
|
+
}),
|
|
531
|
+
);
|
|
532
|
+
|
|
533
|
+
expect(findStep(checklist, "alert-rules")!.detail).toBe(
|
|
534
|
+
"Warning and Critical have no rule.",
|
|
535
|
+
);
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
/*
|
|
539
|
+
* A project can carry sixteen severities. Naming all of them produces a line
|
|
540
|
+
* longer than the tile it sits in, and a line nobody finishes reading says
|
|
541
|
+
* less than a count does.
|
|
542
|
+
*/
|
|
543
|
+
test("stops naming severities after three and counts the rest", () => {
|
|
544
|
+
const many: Array<ReadinessCoverageCellWire> = [
|
|
545
|
+
"Sev1",
|
|
546
|
+
"Sev2",
|
|
547
|
+
"Sev3",
|
|
548
|
+
"Sev4",
|
|
549
|
+
"Sev5",
|
|
550
|
+
].map((name: string, index: number): ReadinessCoverageCellWire => {
|
|
551
|
+
return makeCell({
|
|
552
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
553
|
+
severityId: `severity-${index}`,
|
|
554
|
+
severityName: name,
|
|
555
|
+
hasRule: false,
|
|
556
|
+
});
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
560
|
+
makeInput({
|
|
561
|
+
readiness: makeReadiness({
|
|
562
|
+
status: "PartiallyReady",
|
|
563
|
+
coverage: many,
|
|
564
|
+
}),
|
|
565
|
+
}),
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
expect(findStep(checklist, "incident-rules")!.detail).toBe(
|
|
569
|
+
"Sev1, Sev2, Sev3 and 2 more have no rule.",
|
|
570
|
+
);
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
/*
|
|
574
|
+
* An opted-out cell is deliberate silence, which readiness treats as covered.
|
|
575
|
+
* The checklist must agree, or it will nag somebody about a choice they made
|
|
576
|
+
* on purpose.
|
|
577
|
+
*/
|
|
578
|
+
test("treats an opted-out severity as covered rather than as a gap", () => {
|
|
579
|
+
const coverage: Array<ReadinessCoverageCellWire> = fullCoverage().map(
|
|
580
|
+
(cell: ReadinessCoverageCellWire): ReadinessCoverageCellWire => {
|
|
581
|
+
if (
|
|
582
|
+
cell.ruleType === NotificationRuleType.ON_CALL_EXECUTED_INCIDENT &&
|
|
583
|
+
cell.severityName === "Sev1"
|
|
584
|
+
) {
|
|
585
|
+
return { ...cell, hasRule: false, isOptOut: true };
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
return cell;
|
|
589
|
+
},
|
|
590
|
+
);
|
|
591
|
+
|
|
592
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
593
|
+
makeInput({
|
|
594
|
+
readiness: makeReadiness({ coverage: coverage }),
|
|
595
|
+
}),
|
|
596
|
+
);
|
|
597
|
+
|
|
598
|
+
expect(findStep(checklist, "incident-rules")!.status).toBe(
|
|
599
|
+
SetupStepStatus.Complete,
|
|
600
|
+
);
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
/*
|
|
604
|
+
* The flattery bug. No cells means the project has no severities of that
|
|
605
|
+
* kind, so there is no work and nothing to congratulate - and calling it
|
|
606
|
+
* "Done" would turn into a silent gap the day an admin creates the first one.
|
|
607
|
+
*/
|
|
608
|
+
test("a rule type with no severities at all is not applicable, never complete", () => {
|
|
609
|
+
const incidentOnly: Array<ReadinessCoverageCellWire> =
|
|
610
|
+
fullCoverage().filter((cell: ReadinessCoverageCellWire): boolean => {
|
|
611
|
+
return (
|
|
612
|
+
cell.ruleType === NotificationRuleType.ON_CALL_EXECUTED_INCIDENT ||
|
|
613
|
+
cell.ruleType ===
|
|
614
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE
|
|
615
|
+
);
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
619
|
+
makeInput({
|
|
620
|
+
readiness: makeReadiness({ coverage: incidentOnly }),
|
|
621
|
+
}),
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
const alertStep: SetupStep | undefined = findStep(checklist, "alert-rules");
|
|
625
|
+
|
|
626
|
+
expect(alertStep!.status).toBe(SetupStepStatus.NotApplicable);
|
|
627
|
+
expect(alertStep!.detail).toBe("This project has no alert severities yet.");
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
test("a not-applicable rule type is excluded from the progress total", () => {
|
|
631
|
+
const incidentOnly: Array<ReadinessCoverageCellWire> =
|
|
632
|
+
fullCoverage().filter((cell: ReadinessCoverageCellWire): boolean => {
|
|
633
|
+
return cell.ruleType === NotificationRuleType.ON_CALL_EXECUTED_INCIDENT;
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
const withAlerts: SetupChecklist = buildSetupChecklist(makeInput());
|
|
637
|
+
const withoutAlerts: SetupChecklist = buildSetupChecklist(
|
|
638
|
+
makeInput({
|
|
639
|
+
readiness: makeReadiness({ coverage: incidentOnly }),
|
|
640
|
+
}),
|
|
641
|
+
);
|
|
642
|
+
|
|
643
|
+
// three rule types dropped out of the count, and nothing else changed.
|
|
644
|
+
expect(withoutAlerts.totalCount).toBe(withAlerts.totalCount - 3);
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
test("counts a cell with no severity name rather than naming nothing", () => {
|
|
648
|
+
const unnamed: Array<ReadinessCoverageCellWire> = [
|
|
649
|
+
{
|
|
650
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
651
|
+
hasRule: false,
|
|
652
|
+
isOptOut: false,
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
656
|
+
hasRule: false,
|
|
657
|
+
isOptOut: false,
|
|
658
|
+
},
|
|
659
|
+
];
|
|
660
|
+
|
|
661
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
662
|
+
makeInput({
|
|
663
|
+
readiness: makeReadiness({
|
|
664
|
+
status: "PartiallyReady",
|
|
665
|
+
coverage: unnamed,
|
|
666
|
+
}),
|
|
667
|
+
}),
|
|
668
|
+
);
|
|
669
|
+
|
|
670
|
+
expect(findStep(checklist, "incident-rules")!.detail).toBe(
|
|
671
|
+
"2 severities have no rule.",
|
|
672
|
+
);
|
|
673
|
+
});
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
describe("setup checklist - staying informed", () => {
|
|
677
|
+
test("asks a responder on a schedule to switch on the shift notification", () => {
|
|
678
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
679
|
+
makeInput({
|
|
680
|
+
readiness: makeReadiness({ reachedVia: ["Schedule"] }),
|
|
681
|
+
onCallShiftAlerts: { isKnown: true, hasAnyChannelEnabled: false },
|
|
682
|
+
}),
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
const step: SetupStep | undefined = findStep(
|
|
686
|
+
checklist,
|
|
687
|
+
"on-call-shift-alerts",
|
|
688
|
+
);
|
|
689
|
+
|
|
690
|
+
expect(step!.status).toBe(SetupStepStatus.Incomplete);
|
|
691
|
+
expect(step!.importance).toBe(SetupStepImportance.Recommended);
|
|
692
|
+
expect(step!.pageMap).toBe(PageMap.USER_SETTINGS_NOTIFICATION_SETTINGS);
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
/*
|
|
696
|
+
* A switch about an event that will never fire is not a task. Somebody on no
|
|
697
|
+
* policy has no shifts to be told about.
|
|
698
|
+
*/
|
|
699
|
+
test("omits the shift notification step for somebody who is not on call", () => {
|
|
700
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
701
|
+
makeInput({
|
|
702
|
+
readiness: makeReadiness({ reachedVia: [] }),
|
|
703
|
+
onCallShiftAlerts: { isKnown: true, hasAnyChannelEnabled: false },
|
|
704
|
+
}),
|
|
705
|
+
);
|
|
706
|
+
|
|
707
|
+
expect(stepKeys(checklist)).not.toContain("on-call-shift-alerts");
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
/*
|
|
711
|
+
* The event is emitted when a SCHEDULE's roster rotates. A responder attached
|
|
712
|
+
* directly, through a team or by an override has no roster, so the switch
|
|
713
|
+
* governs something that cannot happen to them.
|
|
714
|
+
*/
|
|
715
|
+
test("omits the shift notification step for a responder with no schedule", () => {
|
|
716
|
+
["Direct", "Team", "Override"].forEach((source: string): void => {
|
|
717
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
718
|
+
makeInput({
|
|
719
|
+
readiness: makeReadiness({
|
|
720
|
+
reachedVia: [source as ResponderSourceValue],
|
|
721
|
+
}),
|
|
722
|
+
onCallShiftAlerts: { isKnown: true, hasAnyChannelEnabled: false },
|
|
723
|
+
}),
|
|
724
|
+
);
|
|
725
|
+
|
|
726
|
+
expect(stepKeys(checklist)).not.toContain("on-call-shift-alerts");
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
test("shows it for somebody reached through both a team and a schedule", () => {
|
|
731
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
732
|
+
makeInput({
|
|
733
|
+
readiness: makeReadiness({ reachedVia: ["Team", "Schedule"] }),
|
|
734
|
+
onCallShiftAlerts: { isKnown: true, hasAnyChannelEnabled: false },
|
|
735
|
+
}),
|
|
736
|
+
);
|
|
737
|
+
|
|
738
|
+
expect(stepKeys(checklist)).toContain("on-call-shift-alerts");
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
test("names the channels that are switched on but cannot deliver", () => {
|
|
742
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
743
|
+
makeInput({
|
|
744
|
+
deliverableSettings: {
|
|
745
|
+
isKnown: true,
|
|
746
|
+
undeliverableChannels: ["SMS", "Call"],
|
|
747
|
+
},
|
|
748
|
+
}),
|
|
749
|
+
);
|
|
750
|
+
|
|
751
|
+
const step: SetupStep | undefined = findStep(
|
|
752
|
+
checklist,
|
|
753
|
+
"deliverable-settings",
|
|
754
|
+
);
|
|
755
|
+
|
|
756
|
+
expect(step!.status).toBe(SetupStepStatus.Incomplete);
|
|
757
|
+
expect(step!.detail).toBe(
|
|
758
|
+
"You switched on SMS and Call, but have no verified method there, so those updates are not sent.",
|
|
759
|
+
);
|
|
760
|
+
expect(step!.pageMap).toBe(PageMap.USER_SETTINGS_NOTIFICATION_METHODS);
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
test("is complete when every switched-on channel has a verified method", () => {
|
|
764
|
+
const checklist: SetupChecklist = buildSetupChecklist(makeInput());
|
|
765
|
+
|
|
766
|
+
expect(findStep(checklist, "deliverable-settings")!.status).toBe(
|
|
767
|
+
SetupStepStatus.Complete,
|
|
768
|
+
);
|
|
769
|
+
});
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
describe("setup checklist - a probe that could not be read", () => {
|
|
773
|
+
/*
|
|
774
|
+
* The single rule these four cases pin: an unknown probe produces NO step.
|
|
775
|
+
* The alternative - defaulting to "not done" - invents a task the reader
|
|
776
|
+
* cannot finish, and defaulting to "done" hides one they should.
|
|
777
|
+
*/
|
|
778
|
+
test("an unreadable notification-settings probe drops both of its steps", () => {
|
|
779
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
780
|
+
makeInput({
|
|
781
|
+
onCallShiftAlerts: { isKnown: false, hasAnyChannelEnabled: false },
|
|
782
|
+
deliverableSettings: { isKnown: false, undeliverableChannels: [] },
|
|
783
|
+
}),
|
|
784
|
+
);
|
|
785
|
+
|
|
786
|
+
expect(stepKeys(checklist)).not.toContain("on-call-shift-alerts");
|
|
787
|
+
expect(stepKeys(checklist)).not.toContain("deliverable-settings");
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
test("an unreadable incoming-call probe drops its step", () => {
|
|
791
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
792
|
+
makeInput({
|
|
793
|
+
incomingCall: {
|
|
794
|
+
isKnown: false,
|
|
795
|
+
hasPolicyInProject: true,
|
|
796
|
+
hasVerifiedNumber: false,
|
|
797
|
+
},
|
|
798
|
+
}),
|
|
799
|
+
);
|
|
800
|
+
|
|
801
|
+
expect(stepKeys(checklist)).not.toContain("incoming-call-number");
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
test("an unreadable workspace probe drops its step", () => {
|
|
805
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
806
|
+
makeInput({
|
|
807
|
+
slack: {
|
|
808
|
+
isKnown: false,
|
|
809
|
+
isConnectedForProject: true,
|
|
810
|
+
isConnectedForUser: false,
|
|
811
|
+
},
|
|
812
|
+
}),
|
|
813
|
+
);
|
|
814
|
+
|
|
815
|
+
expect(stepKeys(checklist)).not.toContain("slack");
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
test("an unreadable custom-field probe drops its step", () => {
|
|
819
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
820
|
+
makeInput({
|
|
821
|
+
customFields: { isKnown: false, fieldCount: 4, filledFieldCount: 0 },
|
|
822
|
+
}),
|
|
823
|
+
);
|
|
824
|
+
|
|
825
|
+
expect(stepKeys(checklist)).not.toContain("custom-fields");
|
|
826
|
+
});
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
describe("setup checklist - optional steps", () => {
|
|
830
|
+
test("shows the incoming call step only when the project routes inbound calls", () => {
|
|
831
|
+
const without: SetupChecklist = buildSetupChecklist(makeInput());
|
|
832
|
+
|
|
833
|
+
expect(stepKeys(without)).not.toContain("incoming-call-number");
|
|
834
|
+
|
|
835
|
+
const withPolicy: SetupChecklist = buildSetupChecklist(
|
|
836
|
+
makeInput({
|
|
837
|
+
incomingCall: {
|
|
838
|
+
isKnown: true,
|
|
839
|
+
hasPolicyInProject: true,
|
|
840
|
+
hasVerifiedNumber: false,
|
|
841
|
+
},
|
|
842
|
+
}),
|
|
843
|
+
);
|
|
844
|
+
|
|
845
|
+
const step: SetupStep | undefined = findStep(
|
|
846
|
+
withPolicy,
|
|
847
|
+
"incoming-call-number",
|
|
848
|
+
);
|
|
849
|
+
|
|
850
|
+
expect(step!.status).toBe(SetupStepStatus.Incomplete);
|
|
851
|
+
expect(step!.importance).toBe(SetupStepImportance.Optional);
|
|
852
|
+
expect(step!.pageMap).toBe(
|
|
853
|
+
PageMap.USER_SETTINGS_INCOMING_CALL_PHONE_NUMBERS,
|
|
854
|
+
);
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
/*
|
|
858
|
+
* Asking somebody to connect a workspace their project has never connected
|
|
859
|
+
* is a task with no possible completion - the Connect button on that page
|
|
860
|
+
* cannot even build its OAuth link.
|
|
861
|
+
*/
|
|
862
|
+
test("shows a workspace step only when the project connected that workspace", () => {
|
|
863
|
+
const notConnected: SetupChecklist = buildSetupChecklist(makeInput());
|
|
864
|
+
|
|
865
|
+
expect(stepKeys(notConnected)).not.toContain("slack");
|
|
866
|
+
expect(stepKeys(notConnected)).not.toContain("microsoft-teams");
|
|
867
|
+
|
|
868
|
+
const connected: SetupChecklist = buildSetupChecklist(
|
|
869
|
+
makeInput({
|
|
870
|
+
slack: {
|
|
871
|
+
isKnown: true,
|
|
872
|
+
isConnectedForProject: true,
|
|
873
|
+
isConnectedForUser: false,
|
|
874
|
+
},
|
|
875
|
+
microsoftTeams: {
|
|
876
|
+
isKnown: true,
|
|
877
|
+
isConnectedForProject: true,
|
|
878
|
+
isConnectedForUser: true,
|
|
879
|
+
},
|
|
880
|
+
}),
|
|
881
|
+
);
|
|
882
|
+
|
|
883
|
+
expect(findStep(connected, "slack")!.status).toBe(
|
|
884
|
+
SetupStepStatus.Incomplete,
|
|
885
|
+
);
|
|
886
|
+
expect(findStep(connected, "microsoft-teams")!.status).toBe(
|
|
887
|
+
SetupStepStatus.Complete,
|
|
888
|
+
);
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
test("shows the custom fields step only when the project defines fields", () => {
|
|
892
|
+
const none: SetupChecklist = buildSetupChecklist(makeInput());
|
|
893
|
+
|
|
894
|
+
expect(stepKeys(none)).not.toContain("custom-fields");
|
|
895
|
+
|
|
896
|
+
const partial: SetupChecklist = buildSetupChecklist(
|
|
897
|
+
makeInput({
|
|
898
|
+
customFields: { isKnown: true, fieldCount: 3, filledFieldCount: 2 },
|
|
899
|
+
}),
|
|
900
|
+
);
|
|
901
|
+
|
|
902
|
+
const step: SetupStep | undefined = findStep(partial, "custom-fields");
|
|
903
|
+
|
|
904
|
+
expect(step!.status).toBe(SetupStepStatus.Incomplete);
|
|
905
|
+
expect(step!.detail).toBe("1 field is still empty.");
|
|
906
|
+
});
|
|
907
|
+
|
|
908
|
+
test("custom fields are complete when every field has a value", () => {
|
|
909
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
910
|
+
makeInput({
|
|
911
|
+
customFields: { isKnown: true, fieldCount: 3, filledFieldCount: 3 },
|
|
912
|
+
}),
|
|
913
|
+
);
|
|
914
|
+
|
|
915
|
+
expect(findStep(checklist, "custom-fields")!.status).toBe(
|
|
916
|
+
SetupStepStatus.Complete,
|
|
917
|
+
);
|
|
918
|
+
expect(findStep(checklist, "custom-fields")!.detail).toBe("");
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
/*
|
|
922
|
+
* The one that keeps the progress bar meaningful: an optional integration
|
|
923
|
+
* must never move somebody towards "ready" while nothing can page them.
|
|
924
|
+
*/
|
|
925
|
+
test("optional steps never change the progress numbers", () => {
|
|
926
|
+
const baseline: SetupChecklist = buildSetupChecklist(makeInput());
|
|
927
|
+
|
|
928
|
+
const withOptional: SetupChecklist = buildSetupChecklist(
|
|
929
|
+
makeInput({
|
|
930
|
+
slack: {
|
|
931
|
+
isKnown: true,
|
|
932
|
+
isConnectedForProject: true,
|
|
933
|
+
isConnectedForUser: true,
|
|
934
|
+
},
|
|
935
|
+
customFields: { isKnown: true, fieldCount: 2, filledFieldCount: 0 },
|
|
936
|
+
incomingCall: {
|
|
937
|
+
isKnown: true,
|
|
938
|
+
hasPolicyInProject: true,
|
|
939
|
+
hasVerifiedNumber: false,
|
|
940
|
+
},
|
|
941
|
+
}),
|
|
942
|
+
);
|
|
943
|
+
|
|
944
|
+
expect(withOptional.totalCount).toBe(baseline.totalCount);
|
|
945
|
+
expect(withOptional.completedCount).toBe(baseline.completedCount);
|
|
946
|
+
});
|
|
947
|
+
|
|
948
|
+
test("the optional section disappears when it would be empty", () => {
|
|
949
|
+
const checklist: SetupChecklist = buildSetupChecklist(makeInput());
|
|
950
|
+
|
|
951
|
+
expect(
|
|
952
|
+
checklist.sections.some((section: SetupSection): boolean => {
|
|
953
|
+
return section.key === "optional";
|
|
954
|
+
}),
|
|
955
|
+
).toBe(false);
|
|
956
|
+
});
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
describe("setup checklist - the headline", () => {
|
|
960
|
+
test("is red when nothing can reach the user", () => {
|
|
961
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
962
|
+
makeInput({
|
|
963
|
+
readiness: makeReadiness({ status: "NotReachable", methods: [] }),
|
|
964
|
+
}),
|
|
965
|
+
);
|
|
966
|
+
|
|
967
|
+
expect(checklist.headlineStatus).toBe(SetupHeadlineStatus.NotReachable);
|
|
968
|
+
expect(checklist.headline).toBe("Nothing can reach you yet");
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
/*
|
|
972
|
+
* Unreachable outranks "not on call". Somebody added to a policy tomorrow is
|
|
973
|
+
* unreachable from that moment, and this is the only screen that would have
|
|
974
|
+
* warned them today.
|
|
975
|
+
*/
|
|
976
|
+
test("says unreachable even for somebody who is not on call yet", () => {
|
|
977
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
978
|
+
makeInput({
|
|
979
|
+
readiness: makeReadiness({
|
|
980
|
+
status: "NotReachable",
|
|
981
|
+
methods: [],
|
|
982
|
+
reachedVia: [],
|
|
983
|
+
}),
|
|
984
|
+
}),
|
|
985
|
+
);
|
|
986
|
+
|
|
987
|
+
expect(checklist.headlineStatus).toBe(SetupHeadlineStatus.NotReachable);
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
test("is amber when there are rule gaps", () => {
|
|
991
|
+
const coverage: Array<ReadinessCoverageCellWire> = fullCoverage().map(
|
|
992
|
+
(cell: ReadinessCoverageCellWire): ReadinessCoverageCellWire => {
|
|
993
|
+
return cell.severityName === "Sev1"
|
|
994
|
+
? { ...cell, hasRule: false }
|
|
995
|
+
: cell;
|
|
996
|
+
},
|
|
997
|
+
);
|
|
998
|
+
|
|
999
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
1000
|
+
makeInput({
|
|
1001
|
+
readiness: makeReadiness({
|
|
1002
|
+
status: "PartiallyReady",
|
|
1003
|
+
coverage: coverage,
|
|
1004
|
+
}),
|
|
1005
|
+
}),
|
|
1006
|
+
);
|
|
1007
|
+
|
|
1008
|
+
expect(checklist.headlineStatus).toBe(SetupHeadlineStatus.NeedsSetup);
|
|
1009
|
+
});
|
|
1010
|
+
|
|
1011
|
+
test("is green, and silent, for a ready responder", () => {
|
|
1012
|
+
const checklist: SetupChecklist = buildSetupChecklist(makeInput());
|
|
1013
|
+
|
|
1014
|
+
expect(checklist.headlineStatus).toBe(SetupHeadlineStatus.Ready);
|
|
1015
|
+
expect(checklist.headlineConsequence).toBe("");
|
|
1016
|
+
});
|
|
1017
|
+
|
|
1018
|
+
test("distinguishes a set-up user who is not on any policy", () => {
|
|
1019
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
1020
|
+
makeInput({
|
|
1021
|
+
readiness: makeReadiness({ reachedVia: [] }),
|
|
1022
|
+
}),
|
|
1023
|
+
);
|
|
1024
|
+
|
|
1025
|
+
expect(checklist.headlineStatus).toBe(SetupHeadlineStatus.NotOnCall);
|
|
1026
|
+
expect(checklist.isOnCallResponder).toBe(false);
|
|
1027
|
+
expect(checklist.headlineConsequence).toBe("");
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
/*
|
|
1031
|
+
* The headline speaks for the whole list. Readiness can be Ready while a
|
|
1032
|
+
* counted step is still outstanding, and "You are all set" printed above a row
|
|
1033
|
+
* the reader still has to do is a contradiction they will notice immediately.
|
|
1034
|
+
*/
|
|
1035
|
+
test("is not green while a counted step is still outstanding", () => {
|
|
1036
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
1037
|
+
makeInput({
|
|
1038
|
+
deliverableSettings: {
|
|
1039
|
+
isKnown: true,
|
|
1040
|
+
undeliverableChannels: ["SMS"],
|
|
1041
|
+
},
|
|
1042
|
+
}),
|
|
1043
|
+
);
|
|
1044
|
+
|
|
1045
|
+
expect(checklist.completedCount).toBeLessThan(checklist.totalCount);
|
|
1046
|
+
expect(checklist.headlineStatus).toBe(SetupHeadlineStatus.NeedsSetup);
|
|
1047
|
+
expect(checklist.headline).not.toBe("You are all set");
|
|
1048
|
+
});
|
|
1049
|
+
|
|
1050
|
+
/*
|
|
1051
|
+
* Every branch of the consequence sentence ends in what happens to "pages
|
|
1052
|
+
* routed to you". No pages are routed to somebody no policy reaches, so the
|
|
1053
|
+
* sentence would describe something that cannot currently happen.
|
|
1054
|
+
*/
|
|
1055
|
+
test("says nothing about consequences to somebody who is not on call", () => {
|
|
1056
|
+
const coverage: Array<ReadinessCoverageCellWire> = fullCoverage().map(
|
|
1057
|
+
(cell: ReadinessCoverageCellWire): ReadinessCoverageCellWire => {
|
|
1058
|
+
return cell.severityName === "Sev1"
|
|
1059
|
+
? { ...cell, hasRule: false }
|
|
1060
|
+
: cell;
|
|
1061
|
+
},
|
|
1062
|
+
);
|
|
1063
|
+
|
|
1064
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
1065
|
+
makeInput({
|
|
1066
|
+
readiness: makeReadiness({
|
|
1067
|
+
status: "PartiallyReady",
|
|
1068
|
+
coverage: coverage,
|
|
1069
|
+
reachedVia: [],
|
|
1070
|
+
}),
|
|
1071
|
+
}),
|
|
1072
|
+
);
|
|
1073
|
+
|
|
1074
|
+
expect(checklist.headlineStatus).toBe(SetupHeadlineStatus.NeedsSetup);
|
|
1075
|
+
expect(checklist.headlineConsequence).toBe("");
|
|
1076
|
+
// the gap is still named on the step itself.
|
|
1077
|
+
expect(findStep(checklist, "incident-rules")!.detail).toBe(
|
|
1078
|
+
"Sev1 has no rule.",
|
|
1079
|
+
);
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
/*
|
|
1083
|
+
* getSelfAddressedConsequence returns a CLAUSE meant to complete "...but ",
|
|
1084
|
+
* which is how the reminder email uses it. Printed here it has to be a
|
|
1085
|
+
* sentence.
|
|
1086
|
+
*/
|
|
1087
|
+
test("renders the consequence as a sentence, not a lowercase fragment", () => {
|
|
1088
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
1089
|
+
makeInput({
|
|
1090
|
+
readiness: makeReadiness({ status: "NotReachable", methods: [] }),
|
|
1091
|
+
}),
|
|
1092
|
+
);
|
|
1093
|
+
|
|
1094
|
+
expect(checklist.headlineConsequence.length).toBeGreaterThan(0);
|
|
1095
|
+
expect(checklist.headlineConsequence.charAt(0)).toBe(
|
|
1096
|
+
checklist.headlineConsequence.charAt(0).toUpperCase(),
|
|
1097
|
+
);
|
|
1098
|
+
expect(checklist.headlineConsequence).toMatch(/^[A-Z]/);
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
test("says pages are dropped when the project has no fallback", () => {
|
|
1102
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
1103
|
+
makeInput({
|
|
1104
|
+
isFallbackEnabled: false,
|
|
1105
|
+
readiness: makeReadiness({ status: "NotReachable", methods: [] }),
|
|
1106
|
+
}),
|
|
1107
|
+
);
|
|
1108
|
+
|
|
1109
|
+
expect(checklist.headlineConsequence).toContain("being dropped");
|
|
1110
|
+
});
|
|
1111
|
+
|
|
1112
|
+
/*
|
|
1113
|
+
* The sentence has exactly two forms - "still reach you" and "are dropped" -
|
|
1114
|
+
* and there is no third that is true either way. If the project's fallback
|
|
1115
|
+
* switch could not be read, the checklist says neither.
|
|
1116
|
+
*/
|
|
1117
|
+
test("says nothing about consequences when the fallback switch is unknown", () => {
|
|
1118
|
+
const coverage: Array<ReadinessCoverageCellWire> = fullCoverage().map(
|
|
1119
|
+
(cell: ReadinessCoverageCellWire): ReadinessCoverageCellWire => {
|
|
1120
|
+
return cell.severityName === "Sev1"
|
|
1121
|
+
? { ...cell, hasRule: false }
|
|
1122
|
+
: cell;
|
|
1123
|
+
},
|
|
1124
|
+
);
|
|
1125
|
+
|
|
1126
|
+
const known: SetupChecklist = buildSetupChecklist(
|
|
1127
|
+
makeInput({
|
|
1128
|
+
readiness: makeReadiness({
|
|
1129
|
+
status: "PartiallyReady",
|
|
1130
|
+
coverage: coverage,
|
|
1131
|
+
}),
|
|
1132
|
+
}),
|
|
1133
|
+
);
|
|
1134
|
+
|
|
1135
|
+
const unknown: SetupChecklist = buildSetupChecklist(
|
|
1136
|
+
makeInput({
|
|
1137
|
+
isFallbackKnown: false,
|
|
1138
|
+
readiness: makeReadiness({
|
|
1139
|
+
status: "PartiallyReady",
|
|
1140
|
+
coverage: coverage,
|
|
1141
|
+
}),
|
|
1142
|
+
}),
|
|
1143
|
+
);
|
|
1144
|
+
|
|
1145
|
+
expect(known.headlineConsequence).not.toBe("");
|
|
1146
|
+
expect(unknown.headlineConsequence).toBe("");
|
|
1147
|
+
// the steps themselves still name every gap.
|
|
1148
|
+
expect(findStep(unknown, "incident-rules")!.detail).toBe(
|
|
1149
|
+
"Sev1 has no rule.",
|
|
1150
|
+
);
|
|
1151
|
+
});
|
|
1152
|
+
});
|
|
1153
|
+
|
|
1154
|
+
describe("setup checklist - shape and progress", () => {
|
|
1155
|
+
test("a fully set-up responder has every counted step complete", () => {
|
|
1156
|
+
const checklist: SetupChecklist = buildSetupChecklist(makeInput());
|
|
1157
|
+
|
|
1158
|
+
expect(checklist.completedCount).toBe(checklist.totalCount);
|
|
1159
|
+
expect(checklist.totalCount).toBeGreaterThan(0);
|
|
1160
|
+
});
|
|
1161
|
+
|
|
1162
|
+
test("progress never exceeds the total", () => {
|
|
1163
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
1164
|
+
makeInput({
|
|
1165
|
+
readiness: makeReadiness({ status: "NotReachable", methods: [] }),
|
|
1166
|
+
slack: {
|
|
1167
|
+
isKnown: true,
|
|
1168
|
+
isConnectedForProject: true,
|
|
1169
|
+
isConnectedForUser: true,
|
|
1170
|
+
},
|
|
1171
|
+
}),
|
|
1172
|
+
);
|
|
1173
|
+
|
|
1174
|
+
expect(checklist.completedCount).toBeLessThanOrEqual(checklist.totalCount);
|
|
1175
|
+
});
|
|
1176
|
+
|
|
1177
|
+
test("reachability comes before paging, which comes before the optional tail", () => {
|
|
1178
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
1179
|
+
makeInput({
|
|
1180
|
+
slack: {
|
|
1181
|
+
isKnown: true,
|
|
1182
|
+
isConnectedForProject: true,
|
|
1183
|
+
isConnectedForUser: false,
|
|
1184
|
+
},
|
|
1185
|
+
}),
|
|
1186
|
+
);
|
|
1187
|
+
|
|
1188
|
+
expect(
|
|
1189
|
+
checklist.sections.map((section: SetupSection): string => {
|
|
1190
|
+
return section.key;
|
|
1191
|
+
}),
|
|
1192
|
+
).toEqual(["reachability", "paging", "awareness", "optional"]);
|
|
1193
|
+
});
|
|
1194
|
+
|
|
1195
|
+
test("every step carries a title, a description and an action", () => {
|
|
1196
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
1197
|
+
makeInput({
|
|
1198
|
+
incomingCall: {
|
|
1199
|
+
isKnown: true,
|
|
1200
|
+
hasPolicyInProject: true,
|
|
1201
|
+
hasVerifiedNumber: false,
|
|
1202
|
+
},
|
|
1203
|
+
slack: {
|
|
1204
|
+
isKnown: true,
|
|
1205
|
+
isConnectedForProject: true,
|
|
1206
|
+
isConnectedForUser: false,
|
|
1207
|
+
},
|
|
1208
|
+
microsoftTeams: {
|
|
1209
|
+
isKnown: true,
|
|
1210
|
+
isConnectedForProject: true,
|
|
1211
|
+
isConnectedForUser: false,
|
|
1212
|
+
},
|
|
1213
|
+
customFields: { isKnown: true, fieldCount: 1, filledFieldCount: 0 },
|
|
1214
|
+
}),
|
|
1215
|
+
);
|
|
1216
|
+
|
|
1217
|
+
allSteps(checklist).forEach((step: SetupStep): void => {
|
|
1218
|
+
expect(step.title.length).toBeGreaterThan(0);
|
|
1219
|
+
expect(step.description.length).toBeGreaterThan(0);
|
|
1220
|
+
expect(step.actionTitle.length).toBeGreaterThan(0);
|
|
1221
|
+
});
|
|
1222
|
+
});
|
|
1223
|
+
|
|
1224
|
+
test("step keys are unique, so the rendered rows cannot collide", () => {
|
|
1225
|
+
const checklist: SetupChecklist = buildSetupChecklist(
|
|
1226
|
+
makeInput({
|
|
1227
|
+
incomingCall: {
|
|
1228
|
+
isKnown: true,
|
|
1229
|
+
hasPolicyInProject: true,
|
|
1230
|
+
hasVerifiedNumber: false,
|
|
1231
|
+
},
|
|
1232
|
+
slack: {
|
|
1233
|
+
isKnown: true,
|
|
1234
|
+
isConnectedForProject: true,
|
|
1235
|
+
isConnectedForUser: false,
|
|
1236
|
+
},
|
|
1237
|
+
microsoftTeams: {
|
|
1238
|
+
isKnown: true,
|
|
1239
|
+
isConnectedForProject: true,
|
|
1240
|
+
isConnectedForUser: false,
|
|
1241
|
+
},
|
|
1242
|
+
customFields: { isKnown: true, fieldCount: 1, filledFieldCount: 0 },
|
|
1243
|
+
}),
|
|
1244
|
+
);
|
|
1245
|
+
|
|
1246
|
+
const keys: Array<string> = stepKeys(checklist);
|
|
1247
|
+
|
|
1248
|
+
expect(new Set<string>(keys).size).toBe(keys.length);
|
|
1249
|
+
});
|
|
1250
|
+
|
|
1251
|
+
/*
|
|
1252
|
+
* Completion is not a stored flag and must not behave like one: adding a
|
|
1253
|
+
* severity, deleting a method or an admin switching a channel off can all
|
|
1254
|
+
* turn a finished step back into an outstanding one.
|
|
1255
|
+
*/
|
|
1256
|
+
test("a step goes back to outstanding when the underlying state regresses", () => {
|
|
1257
|
+
const before: SetupChecklist = buildSetupChecklist(makeInput());
|
|
1258
|
+
|
|
1259
|
+
expect(findStep(before, "incident-rules")!.status).toBe(
|
|
1260
|
+
SetupStepStatus.Complete,
|
|
1261
|
+
);
|
|
1262
|
+
|
|
1263
|
+
const withNewSeverity: Array<ReadinessCoverageCellWire> = [
|
|
1264
|
+
...fullCoverage(),
|
|
1265
|
+
makeCell({
|
|
1266
|
+
ruleType: NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
1267
|
+
severityId: "brand-new",
|
|
1268
|
+
severityName: "Sev3",
|
|
1269
|
+
hasRule: false,
|
|
1270
|
+
}),
|
|
1271
|
+
];
|
|
1272
|
+
|
|
1273
|
+
const after: SetupChecklist = buildSetupChecklist(
|
|
1274
|
+
makeInput({
|
|
1275
|
+
readiness: makeReadiness({
|
|
1276
|
+
status: "PartiallyReady",
|
|
1277
|
+
coverage: withNewSeverity,
|
|
1278
|
+
}),
|
|
1279
|
+
}),
|
|
1280
|
+
);
|
|
1281
|
+
|
|
1282
|
+
expect(findStep(after, "incident-rules")!.status).toBe(
|
|
1283
|
+
SetupStepStatus.Incomplete,
|
|
1284
|
+
);
|
|
1285
|
+
expect(after.completedCount).toBeLessThan(before.completedCount);
|
|
1286
|
+
});
|
|
1287
|
+
|
|
1288
|
+
/*
|
|
1289
|
+
* The paging section explains itself differently depending on whether the
|
|
1290
|
+
* reader is on call, because "you are on call" is the fact that makes the
|
|
1291
|
+
* four rule pages urgent rather than hypothetical.
|
|
1292
|
+
*/
|
|
1293
|
+
test("the paging section tells a responder they are on call", () => {
|
|
1294
|
+
const responder: SetupChecklist = buildSetupChecklist(makeInput());
|
|
1295
|
+
const notResponder: SetupChecklist = buildSetupChecklist(
|
|
1296
|
+
makeInput({
|
|
1297
|
+
readiness: makeReadiness({ reachedVia: [] }),
|
|
1298
|
+
}),
|
|
1299
|
+
);
|
|
1300
|
+
|
|
1301
|
+
const pagingOf: (checklist: SetupChecklist) => SetupSection = (
|
|
1302
|
+
checklist: SetupChecklist,
|
|
1303
|
+
): SetupSection => {
|
|
1304
|
+
return checklist.sections.find((section: SetupSection): boolean => {
|
|
1305
|
+
return section.key === "paging";
|
|
1306
|
+
})!;
|
|
1307
|
+
};
|
|
1308
|
+
|
|
1309
|
+
expect(pagingOf(responder).description).toContain("You are on call");
|
|
1310
|
+
expect(pagingOf(notResponder).description).toContain("not on an on-call");
|
|
1311
|
+
});
|
|
1312
|
+
});
|