@oneuptime/common 13.0.1 → 13.0.4
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/RumSession.ts +34 -0
- package/Models/DatabaseModels/AlertEpisodeLabelRule.ts +2 -2
- package/Models/DatabaseModels/AlertEpisodeOnCallRule.ts +2 -2
- package/Models/DatabaseModels/AlertEpisodeOwnerRule.ts +2 -2
- package/Models/DatabaseModels/AlertEpisodePrivacyRule.ts +2 -2
- package/Models/DatabaseModels/AlertGroupingRule.ts +2 -2
- package/Models/DatabaseModels/AlertLabelRule.ts +2 -2
- package/Models/DatabaseModels/AlertOnCallRule.ts +2 -2
- package/Models/DatabaseModels/AlertOwnerRule.ts +2 -2
- package/Models/DatabaseModels/AlertPrivacyRule.ts +2 -2
- package/Models/DatabaseModels/AlertReminderRule.ts +6 -4
- package/Models/DatabaseModels/AutoRemediationRule.ts +2 -2
- package/Models/DatabaseModels/CephClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/CephClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/CloudResourceLabelRule.ts +2 -2
- package/Models/DatabaseModels/CloudResourceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/DashboardLabelRule.ts +2 -2
- package/Models/DatabaseModels/DashboardOwnerRule.ts +2 -2
- package/Models/DatabaseModels/DatabaseBaseModel/RelationOnlyRuleBaseModel.ts +11 -0
- package/Models/DatabaseModels/DatabaseBaseModel/RuleBaseModel.ts +44 -0
- package/Models/DatabaseModels/DockerHostLabelRule.ts +2 -2
- package/Models/DatabaseModels/DockerHostOwnerRule.ts +2 -2
- package/Models/DatabaseModels/DockerSwarmClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/DockerSwarmClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/HostLabelRule.ts +2 -2
- package/Models/DatabaseModels/HostOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodeLabelRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodeOnCallRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodeOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncidentEpisodePrivacyRule.ts +2 -2
- package/Models/DatabaseModels/IncidentGroupingRule.ts +2 -2
- package/Models/DatabaseModels/IncidentLabelRule.ts +2 -2
- package/Models/DatabaseModels/IncidentOnCallRule.ts +2 -2
- package/Models/DatabaseModels/IncidentOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncidentPrivacyRule.ts +2 -2
- package/Models/DatabaseModels/IncidentReminderRule.ts +6 -4
- package/Models/DatabaseModels/IncidentSlaRule.ts +2 -2
- package/Models/DatabaseModels/IncomingCallPolicy.ts +3 -4
- package/Models/DatabaseModels/IncomingCallPolicyLabelRule.ts +2 -2
- package/Models/DatabaseModels/IncomingCallPolicyOwnerRule.ts +2 -2
- package/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.ts +254 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/IoTFleetLabelRule.ts +2 -2
- package/Models/DatabaseModels/IoTFleetOwnerRule.ts +2 -2
- package/Models/DatabaseModels/KubernetesClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/KubernetesClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/MonitorLabelRule.ts +2 -2
- package/Models/DatabaseModels/MonitorOwnerRule.ts +2 -2
- package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +2 -2
- package/Models/DatabaseModels/NetworkDeviceLabelRule.ts +2 -2
- package/Models/DatabaseModels/NetworkDeviceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyLabelRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyOwnerRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleLabelRule.ts +2 -2
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerRule.ts +2 -2
- package/Models/DatabaseModels/PodmanHostLabelRule.ts +2 -2
- package/Models/DatabaseModels/PodmanHostOwnerRule.ts +2 -2
- package/Models/DatabaseModels/ProxmoxClusterLabelRule.ts +2 -2
- package/Models/DatabaseModels/ProxmoxClusterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/RumApplicationLabelRule.ts +2 -2
- package/Models/DatabaseModels/RumApplicationOwnerRule.ts +2 -2
- package/Models/DatabaseModels/RunbookLabelRule.ts +2 -2
- package/Models/DatabaseModels/RunbookOwnerRule.ts +2 -2
- package/Models/DatabaseModels/RunbookRule.ts +2 -2
- package/Models/DatabaseModels/ScheduledMaintenanceLabelRule.ts +2 -2
- package/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/ScheduledMaintenanceReminderRule.ts +6 -4
- package/Models/DatabaseModels/ServerlessFunctionLabelRule.ts +2 -2
- package/Models/DatabaseModels/ServerlessFunctionOwnerRule.ts +2 -2
- package/Models/DatabaseModels/ServiceLabelRule.ts +2 -2
- package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +283 -4
- package/Models/DatabaseModels/ServiceOwnerRule.ts +2 -2
- package/Models/DatabaseModels/StatusPageLabelRule.ts +2 -2
- package/Models/DatabaseModels/StatusPageMonitorRule.ts +2 -2
- package/Models/DatabaseModels/StatusPageOwnerRule.ts +2 -2
- package/Models/DatabaseModels/VMwareVCenterLabelRule.ts +2 -2
- package/Models/DatabaseModels/VMwareVCenterOwnerRule.ts +2 -2
- package/Models/DatabaseModels/WorkflowLabelRule.ts +2 -2
- package/Models/DatabaseModels/WorkflowOwnerRule.ts +2 -2
- package/Server/API/TelemetryAPI.ts +323 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792400000000-AddSloBurnRateRuleIncidents.ts +111 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792500000000-AddConfigurableRuleCriteria.ts +644 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792600000000-AddIncomingCallPolicyPhoneNumbers.ts +72 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/MultipartFormData.ts +46 -21
- package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +21 -0
- package/Server/Services/AlertEpisodeOnCallRuleEngineService.ts +21 -0
- package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +21 -0
- package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +21 -0
- package/Server/Services/AlertGroupingEngineService.ts +27 -0
- package/Server/Services/AlertLabelRuleEngineService.ts +27 -0
- package/Server/Services/AlertOnCallRuleEngineService.ts +27 -0
- package/Server/Services/AlertOwnerRuleEngineService.ts +27 -0
- package/Server/Services/AlertPrivacyRuleEngineService.ts +27 -0
- package/Server/Services/AlertReminderRuleService.ts +65 -33
- package/Server/Services/AutoRemediationRuleEngineService.ts +90 -8
- package/Server/Services/CephClusterLabelRuleEngineService.ts +20 -0
- package/Server/Services/CephClusterOwnerRuleEngineService.ts +20 -0
- package/Server/Services/CloudResourceLabelRuleEngineService.ts +20 -0
- package/Server/Services/CloudResourceOwnerRuleEngineService.ts +20 -0
- package/Server/Services/DashboardLabelRuleEngineService.ts +20 -0
- package/Server/Services/DashboardOwnerRuleEngineService.ts +20 -0
- package/Server/Services/DatabaseService.ts +409 -6
- package/Server/Services/DockerHostLabelRuleEngineService.ts +20 -0
- package/Server/Services/DockerHostOwnerRuleEngineService.ts +20 -0
- package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +23 -0
- package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +23 -0
- package/Server/Services/HostLabelRuleEngineService.ts +13 -0
- package/Server/Services/HostOwnerRuleEngineService.ts +13 -0
- package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +21 -0
- package/Server/Services/IncidentEpisodeOnCallRuleEngineService.ts +21 -0
- package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +21 -0
- package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +21 -0
- package/Server/Services/IncidentGroupingEngineService.ts +64 -13
- package/Server/Services/IncidentLabelRuleEngineService.ts +64 -9
- package/Server/Services/IncidentOnCallRuleEngineService.ts +64 -10
- package/Server/Services/IncidentOwnerRuleEngineService.ts +64 -10
- package/Server/Services/IncidentPrivacyRuleEngineService.ts +64 -10
- package/Server/Services/IncidentReminderRuleService.ts +66 -34
- package/Server/Services/IncidentSlaRuleService.ts +55 -12
- package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +20 -0
- package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +20 -0
- package/Server/Services/IncomingCallPolicyPhoneNumberService.ts +184 -0
- package/Server/Services/IncomingCallPolicyService.ts +276 -5
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/IoTFleetLabelRuleEngineService.ts +20 -0
- package/Server/Services/IoTFleetOwnerRuleEngineService.ts +20 -0
- package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +23 -0
- package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +23 -0
- package/Server/Services/LabelService.ts +50 -7
- package/Server/Services/MonitorLabelRuleEngineService.ts +20 -0
- package/Server/Services/MonitorOwnerRuleEngineService.ts +20 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +2 -0
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +93 -1
- package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +26 -0
- package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +25 -0
- package/Server/Services/NetworkDeviceService.ts +2 -0
- package/Server/Services/NetworkSiteAssignmentRuleService.ts +90 -1
- package/Server/Services/NetworkSiteService.ts +242 -29
- package/Server/Services/NetworkSiteTypeService.ts +177 -77
- package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +20 -0
- package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +20 -0
- package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +22 -0
- package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +22 -0
- package/Server/Services/PodmanHostLabelRuleEngineService.ts +20 -0
- package/Server/Services/PodmanHostOwnerRuleEngineService.ts +20 -0
- package/Server/Services/ProjectCallSMSConfigService.ts +156 -7
- package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +25 -0
- package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +25 -0
- package/Server/Services/RumApplicationLabelRuleEngineService.ts +22 -0
- package/Server/Services/RumApplicationOwnerRuleEngineService.ts +22 -0
- package/Server/Services/RunbookLabelRuleEngineService.ts +20 -0
- package/Server/Services/RunbookOwnerRuleEngineService.ts +20 -0
- package/Server/Services/RunbookRuleEngineService.ts +18 -1
- package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +62 -10
- package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +62 -11
- package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +48 -18
- package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +25 -0
- package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +25 -0
- package/Server/Services/ServiceLabelRuleEngineService.ts +20 -0
- package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +675 -12
- package/Server/Services/ServiceLevelObjectiveService.ts +55 -13
- package/Server/Services/ServiceOwnerRuleEngineService.ts +20 -0
- package/Server/Services/StatusPageLabelRuleEngineService.ts +20 -0
- package/Server/Services/StatusPageMonitorRuleEngineService.ts +31 -2
- package/Server/Services/StatusPageMonitorRuleService.ts +34 -1
- package/Server/Services/StatusPageOwnerRuleEngineService.ts +20 -0
- package/Server/Services/UserService.ts +23 -50
- package/Server/Services/VMwareVCenterLabelRuleEngineService.ts +25 -0
- package/Server/Services/VMwareVCenterOwnerRuleEngineService.ts +25 -0
- package/Server/Services/WorkflowLabelRuleEngineService.ts +20 -0
- package/Server/Services/WorkflowOwnerRuleEngineService.ts +20 -0
- package/Server/Static/Brand/README.md +10 -5
- package/Server/Static/Brand/favicons/oneuptime-up-v1.svg +8 -0
- package/Server/Types/Database/QueryHelper.ts +88 -0
- package/Server/Utils/AI/Toolbox/SloTools.ts +19 -2
- package/Server/Utils/IncomingCallPhoneNumber.ts +29 -16
- package/Server/Utils/Profiling.ts +13 -1
- package/Server/Utils/Rules/MonitorRuleCriteriaCache.ts +38 -0
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +498 -0
- package/Server/Utils/Telemetry.ts +3 -1
- package/Server/Utils/VendorAssets.ts +3 -0
- package/Tests/App/Dashboard/AIInsightViewTriage.test.tsx +348 -0
- package/Tests/App/Dashboard/ArchiveResourceCard.test.tsx +476 -0
- package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +25 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +449 -24
- package/Tests/App/Dashboard/DashboardPersistentSideMenuLayouts.test.tsx +702 -0
- package/Tests/App/Dashboard/ExceptionsLandingRedirect.test.tsx +63 -0
- package/Tests/App/Dashboard/FeedOrdering.test.ts +150 -0
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +279 -100
- package/Tests/App/Dashboard/InventoryItemSideMenu.test.tsx +155 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +11 -0
- package/Tests/App/Dashboard/PasskeySettings.test.tsx +215 -71
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +347 -0
- package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +263 -0
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +413 -17
- package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +138 -0
- package/Tests/App/Dashboard/SloDashboardTemplateWidgets.test.tsx +940 -0
- package/Tests/App/Dashboard/TelemetryIngestionKeyEdit.test.tsx +378 -0
- package/Tests/App/Dashboard/TelemetryIngestionKeyForm.test.tsx +735 -0
- package/Tests/App/Dashboard/TwoFactorStatus.test.tsx +275 -108
- package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +13 -3
- package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +127 -4
- package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +5 -4
- package/Tests/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.test.ts +362 -0
- package/Tests/Models/DatabaseModels/RuleBaseModel.test.ts +69 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +181 -0
- package/Tests/Server/API/SessionReplayAPI.test.ts +1303 -145
- package/Tests/Server/API/UserTwoFactorSelfService.test.ts +407 -0
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +611 -0
- package/Tests/Server/Middleware/MultipartFormData.test.ts +61 -3
- package/Tests/Server/Middleware/TelemetryIngestionDisabled.test.ts +211 -0
- package/Tests/Server/Services/AlertIncidentRuleCriteriaEngineServices.test.ts +651 -0
- package/Tests/Server/Services/AutoRemediationRuleEngineService.test.ts +79 -0
- package/Tests/Server/Services/DatabaseServiceRelationOnlyRuleRollout.test.ts +330 -0
- package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +522 -0
- package/Tests/Server/Services/IncidentSlaRuleCriteriaCorrelation.test.ts +99 -0
- package/Tests/Server/Services/IncomingCallPolicyPhoneNumberService.test.ts +1540 -0
- package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +179 -2
- package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +170 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +559 -53
- package/Tests/Server/Services/NetworkSiteTypeService.test.ts +122 -55
- package/Tests/Server/Services/ReminderRuleCriteria.test.ts +173 -0
- package/Tests/Server/Services/ResourceRuleCriteriaEngineServices.test.ts +170 -0
- package/Tests/Server/Services/ScheduledMaintenanceRuleCriteriaCorrelation.test.ts +154 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +2450 -470
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +464 -121
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +281 -0
- package/Tests/Server/Services/StatusPageMonitorRuleEngineService.test.ts +132 -0
- package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +159 -14
- package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +6 -8
- package/Tests/Server/Services/UserTwoFactorAuthAdmin.test.ts +203 -34
- package/Tests/Server/Types/Database/QueryHelperJsonArrayObjects.test.ts +128 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +190 -1
- package/Tests/Server/Utils/AI/Toolbox/AIToolbox.test.ts +461 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +25 -0
- package/Tests/Server/Utils/Billing/BillingFailureNoticeThrottle.test.ts +359 -0
- package/Tests/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.test.ts +318 -0
- package/Tests/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.test.ts +220 -0
- package/Tests/Server/Utils/Dashboard/SloTemplatePublicDashboard.test.ts +1043 -0
- package/Tests/Server/Utils/Execute.test.ts +302 -0
- package/Tests/Server/Utils/GracefulShutdown.test.ts +565 -0
- package/Tests/Server/Utils/IncomingCallPhoneNumber.test.ts +36 -20
- package/Tests/Server/Utils/LoggerCore.test.ts +597 -0
- package/Tests/Server/Utils/Monitor/MonitorTemplateUtil.test.ts +1109 -0
- package/Tests/Server/Utils/Monitor/SloTemplateMetricEmitterContract.test.ts +750 -0
- package/Tests/Server/Utils/ProductAnalytics.test.ts +404 -0
- package/Tests/Server/Utils/Profiling.test.ts +366 -0
- package/Tests/Server/Utils/Rules/MonitorRuleCriteriaCache.test.ts +99 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +558 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +711 -0
- package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +522 -0
- package/Tests/Server/Utils/VendorAssets.test.ts +17 -0
- package/Tests/Types/Dashboard/DashboardTemplateEditorialInvariants.test.ts +659 -0
- package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +97 -0
- package/Tests/Types/Dashboard/SloDashboardTemplate.test.ts +1179 -0
- package/Tests/Types/Database/AccessControl/OwnedThrough.test.ts +136 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilCorePaths.test.ts +1014 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveRotation.test.ts +9 -6
- package/Tests/Types/Rules/RuleCriteriaFieldRegistry.test.ts +276 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +180 -1
- package/Tests/Types/Telemetry/LlmConventions.test.ts +495 -0
- package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +13 -6
- package/Tests/UI/Components/Alert.test.tsx +532 -93
- package/Tests/UI/Components/Feed.test.tsx +241 -0
- package/Tests/UI/Components/Forms/BasicFormStepNavigation.test.tsx +368 -0
- package/Tests/UI/Components/Forms/FormSummary.test.tsx +454 -0
- package/Tests/UI/Components/Forms/ModelFormJsonColumns.test.tsx +290 -0
- package/Tests/UI/Components/Forms/ModelFormRuleCriteria.test.tsx +331 -0
- package/Tests/UI/Components/IconOpticalSize.test.tsx +79 -31
- package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +6 -6
- package/Tests/UI/Components/NavBar.test.tsx +91 -2
- package/Tests/UI/Components/PencilButton.test.tsx +211 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaBuilder.test.tsx +510 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +350 -0
- package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +50 -0
- package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +329 -0
- package/Tests/UI/Components/useFeedItems.test.tsx +107 -0
- package/Tests/UI/Rum/ChunkLoader.test.ts +401 -0
- package/Tests/UI/Rum/RecordingHealthCard.test.tsx +1 -1
- package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +7 -1
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +2 -0
- package/Tests/UI/Rum/ReplayEngine.test.ts +1069 -5
- package/Tests/UI/Rum/ReplayHeader.test.tsx +579 -2
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +23 -5
- package/Tests/UI/Rum/ReplayRail.test.tsx +143 -1
- package/Tests/UI/Rum/ReplayRenderBudget.test.tsx +338 -0
- package/Tests/UI/Rum/ReplaySignals.test.ts +179 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +210 -3
- package/Tests/UI/Rum/ReplayTimeline.test.tsx +180 -1
- package/Tests/UI/Rum/ReplayUserSessionsMenu.test.tsx +405 -0
- package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +13 -16
- package/Tests/UI/Rum/SessionReplayFacets.test.tsx +199 -0
- package/Tests/UI/Rum/SessionReplaySearchBar.test.tsx +58 -21
- package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +2 -0
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +717 -4
- package/Tests/UI/Rum/SessionReplayUsersPage.test.tsx +435 -0
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +577 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +1 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +1 -1
- package/Tests/UI/Utils/LabelRuleImportExport.test.ts +192 -0
- package/Tests/UI/Utils/Navigation.test.ts +30 -0
- package/Tests/Utils/Dashboard/SloTemplateVariableScoping.test.ts +880 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +158 -0
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +93 -0
- package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +138 -0
- package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +174 -0
- package/Tests/Utils/Rules/RuleCriteriaMatcher.test.ts +1424 -0
- package/Tests/Utils/Rum/SessionIdentity.test.ts +72 -0
- package/Tests/Utils/Rum/SessionReplayHealth.test.ts +884 -0
- package/Tests/Utils/Slo/SloBurnRateRuleState.test.ts +374 -28
- package/Tests/Utils/Telemetry/OriginAllowList.test.ts +118 -0
- package/Types/Dashboard/DashboardTemplates.ts +465 -0
- package/Types/OnCallDutyPolicy/Layer.ts +12 -0
- package/Types/Rules/RuleCriteria.ts +51 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +449 -0
- package/Types/Rum/SessionReplay.ts +75 -0
- package/Types/Rum/SessionReplayApi.ts +93 -0
- package/UI/Components/Alerts/Alert.tsx +102 -72
- package/UI/Components/Button/Button.tsx +4 -1
- package/UI/Components/Dropdown/Dropdown.tsx +2 -0
- package/UI/Components/Feed/Feed.tsx +15 -0
- package/UI/Components/Feed/useFeedItems.ts +227 -0
- package/UI/Components/Forms/BasicForm.tsx +42 -21
- package/UI/Components/Forms/ModelForm.tsx +80 -1
- package/UI/Components/Icon/Icon.tsx +3 -35
- package/UI/Components/ModelTable/ModelTable.tsx +19 -0
- package/UI/Components/Navbar/NavBar.tsx +1 -0
- package/UI/Components/RuleCriteria/RuleCriteriaBuilder.tsx +735 -0
- package/UI/Components/RuleCriteria/RuleCriteriaModelForm.tsx +209 -0
- package/UI/Components/RuleCriteria/RuleCriteriaModelTable.tsx +205 -0
- package/UI/Components/RuleCriteria/RuleCriteriaSummary.tsx +123 -0
- package/UI/Components/Table/Table.tsx +3 -0
- package/UI/Components/Table/TableBody.tsx +3 -0
- package/UI/Components/Table/TableRow.tsx +8 -2
- package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +14 -2
- package/UI/Styles/Theme.css +1 -0
- package/UI/Utils/LabelRuleImportExport.ts +114 -6
- package/UI/Utils/Navigation.ts +1 -2
- package/UI/esbuild-config.js +46 -0
- package/Utils/Faker.ts +93 -6
- package/Utils/LabelRuleImportExport.ts +295 -2
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +108 -8
- package/Utils/NetworkSite/CidrMatchUtil.ts +102 -0
- package/Utils/NetworkSite/TypeHierarchyUtil.ts +152 -2
- package/Utils/Rules/RuleCriteriaMatcher.ts +931 -0
- package/Utils/Rum/SessionIdentity.ts +16 -0
- package/Utils/Slo/SloBurnRateRuleState.ts +87 -33
- package/Utils/Telemetry/OriginAllowList.ts +74 -0
- package/build/dist/Models/AnalyticsModels/RumSession.js +32 -0
- package/build/dist/Models/AnalyticsModels/RumSession.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodeLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodeOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodePrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertEpisodePrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertPrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AlertPrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertReminderRule.js +6 -5
- package/build/dist/Models/DatabaseModels/AlertReminderRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AutoRemediationRule.js +2 -2
- package/build/dist/Models/DatabaseModels/AutoRemediationRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResourceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CloudResourceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResourceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/CloudResourceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DashboardLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DashboardLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DashboardOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DashboardOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RelationOnlyRuleBaseModel.js +12 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RelationOnlyRuleBaseModel.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RuleBaseModel.js +50 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/RuleBaseModel.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DockerHostLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerHostLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHostOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerHostOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/HostLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/HostLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/HostOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/HostOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodeLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentEpisodePrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentOnCallRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentOnCallRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPrivacyRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentPrivacyRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentReminderRule.js +6 -5
- package/build/dist/Models/DatabaseModels/IncidentReminderRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentSlaRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncidentSlaRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js +3 -4
- package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.js +277 -0
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyPhoneNumber.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IoTFleetLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/IoTFleetOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/KubernetesClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/MonitorLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/MonitorOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +2 -2
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHostLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/PodmanHostLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanHostOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/PodmanHostOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplicationLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RumApplicationLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplicationOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RumApplicationOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunbookLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RunbookLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunbookOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RunbookOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunbookRule.js +2 -2
- package/build/dist/Models/DatabaseModels/RunbookRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceReminderRule.js +6 -5
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceReminderRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunctionLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServerlessFunctionLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServiceLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +281 -4
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/ServiceOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/StatusPageLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js +2 -2
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/StatusPageOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenterLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/VMwareVCenterLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowLabelRule.js +2 -2
- package/build/dist/Models/DatabaseModels/WorkflowLabelRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowOwnerRule.js +2 -2
- package/build/dist/Models/DatabaseModels/WorkflowOwnerRule.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +211 -4
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792400000000-AddSloBurnRateRuleIncidents.js +60 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792400000000-AddSloBurnRateRuleIncidents.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792500000000-AddConfigurableRuleCriteria.js +301 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792500000000-AddConfigurableRuleCriteria.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792600000000-AddIncomingCallPolicyPhoneNumbers.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792600000000-AddIncomingCallPolicyPhoneNumbers.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MultipartFormData.js +38 -21
- package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +17 -0
- package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertGroupingEngineService.js +21 -0
- package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOnCallRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +21 -0
- package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertReminderRuleService.js +44 -26
- package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +54 -11
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +235 -10
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostLabelRuleEngineService.js +12 -0
- package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js +12 -0
- package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +17 -0
- package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +39 -13
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +39 -9
- package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js +39 -10
- package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +39 -10
- package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +39 -10
- package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentReminderRuleService.js +44 -26
- package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSlaRuleService.js +33 -12
- package/build/dist/Server/Services/IncidentSlaRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallPolicyPhoneNumberService.js +127 -0
- package/build/dist/Server/Services/IncomingCallPolicyPhoneNumberService.js.map +1 -0
- package/build/dist/Server/Services/IncomingCallPolicyService.js +187 -4
- package/build/dist/Server/Services/IncomingCallPolicyService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +39 -7
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +2 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +57 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +17 -0
- package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +2 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +56 -1
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +187 -22
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteTypeService.js +126 -51
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProjectCallSMSConfigService.js +115 -6
- package/build/dist/Server/Services/ProjectCallSMSConfigService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/RunbookRuleEngineService.js +12 -0
- package/build/dist/Server/Services/RunbookRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +38 -9
- package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +38 -10
- package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +32 -14
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +554 -12
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +50 -14
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +25 -2
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js +19 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +14 -49
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +16 -0
- package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +16 -0
- package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +67 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +21 -4
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
- package/build/dist/Server/Utils/IncomingCallPhoneNumber.js +9 -3
- package/build/dist/Server/Utils/IncomingCallPhoneNumber.js.map +1 -1
- package/build/dist/Server/Utils/Profiling.js +10 -1
- package/build/dist/Server/Utils/Profiling.js.map +1 -1
- package/build/dist/Server/Utils/Rules/MonitorRuleCriteriaCache.js +30 -0
- package/build/dist/Server/Utils/Rules/MonitorRuleCriteriaCache.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +344 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry.js +1 -1
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +2 -0
- package/build/dist/Server/Utils/VendorAssets.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +425 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +11 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteria.js +18 -0
- package/build/dist/Types/Rules/RuleCriteria.js.map +1 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +435 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplay.js +64 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
- package/build/dist/UI/Components/Alerts/Alert.js +63 -41
- package/build/dist/UI/Components/Alerts/Alert.js.map +1 -1
- package/build/dist/UI/Components/Button/Button.js +3 -1
- package/build/dist/UI/Components/Button/Button.js.map +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js +1 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/Feed/Feed.js +4 -1
- package/build/dist/UI/Components/Feed/Feed.js.map +1 -1
- package/build/dist/UI/Components/Feed/useFeedItems.js +137 -0
- package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -0
- package/build/dist/UI/Components/Forms/BasicForm.js +38 -19
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +65 -1
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +3 -35
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js +12 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +1 -0
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaBuilder.js +383 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaBuilder.js.map +1 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelForm.js +124 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelForm.js.map +1 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelTable.js +126 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaModelTable.js.map +1 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaSummary.js +63 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaSummary.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +1 -1
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableBody.js +4 -2
- package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +3 -2
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +14 -2
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +1 -1
- package/build/dist/UI/Utils/LabelRuleImportExport.js +81 -5
- package/build/dist/UI/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/Utils/Faker.js +76 -6
- package/build/dist/Utils/Faker.js.map +1 -1
- package/build/dist/Utils/LabelRuleImportExport.js +157 -3
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +81 -5
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +77 -0
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +109 -2
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -1
- package/build/dist/Utils/Rules/RuleCriteriaMatcher.js +526 -0
- package/build/dist/Utils/Rules/RuleCriteriaMatcher.js.map +1 -0
- package/build/dist/Utils/Rum/SessionIdentity.js +13 -1
- package/build/dist/Utils/Rum/SessionIdentity.js.map +1 -1
- package/build/dist/Utils/Slo/SloBurnRateRuleState.js +28 -15
- package/build/dist/Utils/Slo/SloBurnRateRuleState.js.map +1 -1
- package/build/dist/Utils/Telemetry/OriginAllowList.js +61 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -1
- package/package.json +20 -20
|
@@ -0,0 +1,940 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import {
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
jest,
|
|
8
|
+
test,
|
|
9
|
+
} from "@jest/globals";
|
|
10
|
+
import {
|
|
11
|
+
RenderResult,
|
|
12
|
+
cleanup,
|
|
13
|
+
render,
|
|
14
|
+
screen,
|
|
15
|
+
waitFor,
|
|
16
|
+
} from "@testing-library/react";
|
|
17
|
+
import * as React from "react";
|
|
18
|
+
import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
* Mounts the widgets the SLO dashboard template actually ships — every one of
|
|
22
|
+
* them, taken from getTemplateConfig(DashboardTemplateType.Slo) — through the
|
|
23
|
+
* REAL renderers.
|
|
24
|
+
*
|
|
25
|
+
* Everything else in the repo reads this template as a data structure: the
|
|
26
|
+
* editorial suite (Types/Dashboard/SloDashboardTemplate.test.ts) pins which
|
|
27
|
+
* widgets it carries and what arguments they hold, and the invariants suite
|
|
28
|
+
* pins the grid. Neither ever renders one, so nothing catches the case where
|
|
29
|
+
* the shipped ARGUMENTS and the renderer disagree: a template widget stuck on
|
|
30
|
+
* its loading skeleton, a tile printing "null%" before the evaluation worker
|
|
31
|
+
* has run, a chart drawing a broken frame over an empty series, or the one
|
|
32
|
+
* guidance row rendering empty.
|
|
33
|
+
*
|
|
34
|
+
* Every assertion below starts from the template config rather than from
|
|
35
|
+
* hand-built components, so a seventh SLO widget added to the template is
|
|
36
|
+
* covered here without editing this file.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
const getItemMock: MockFunction = getJestMockFunction();
|
|
40
|
+
const getListMock: MockFunction = getJestMockFunction();
|
|
41
|
+
const aggregateMock: MockFunction = getJestMockFunction();
|
|
42
|
+
const getCurrentProjectIdMock: MockFunction = getJestMockFunction();
|
|
43
|
+
const lineChartRenderMock: MockFunction = getJestMockFunction();
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* The arrow wrappers are load bearing: jest.mock is hoisted above the compiled
|
|
47
|
+
* requires, so the mock variables above are still unassigned when the factory
|
|
48
|
+
* runs. Dereferencing them lazily, at call time, is what makes this work.
|
|
49
|
+
*/
|
|
50
|
+
jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
|
|
51
|
+
return {
|
|
52
|
+
__esModule: true,
|
|
53
|
+
default: {
|
|
54
|
+
getItem: (...args: Array<any>) => {
|
|
55
|
+
return getItemMock(...args);
|
|
56
|
+
},
|
|
57
|
+
getList: (...args: Array<any>) => {
|
|
58
|
+
return getListMock(...args);
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
jest.mock("../../../UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI", () => {
|
|
65
|
+
return {
|
|
66
|
+
__esModule: true,
|
|
67
|
+
default: {
|
|
68
|
+
aggregate: (...args: Array<any>) => {
|
|
69
|
+
return aggregateMock(...args);
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
jest.mock("../../../UI/Utils/Project", () => {
|
|
76
|
+
return {
|
|
77
|
+
__esModule: true,
|
|
78
|
+
default: {
|
|
79
|
+
getCurrentProjectId: (...args: Array<any>) => {
|
|
80
|
+
return getCurrentProjectIdMock(...args);
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
* recharts measures a 0x0 parent in jsdom, so the real chart would draw
|
|
88
|
+
* nothing and every "did it mount a chart" assertion would pass for the wrong
|
|
89
|
+
* reason. The stub records the props instead — which is where the reference
|
|
90
|
+
* line lives — and renders a marker the assertions can count.
|
|
91
|
+
*
|
|
92
|
+
* (The real recharts SVG is exercised by SloWidgetChartRendering.test.tsx;
|
|
93
|
+
* what is pinned here is which of the TEMPLATE's charts gets a target line.)
|
|
94
|
+
*/
|
|
95
|
+
jest.mock("../../../UI/Components/Charts/Line/LineChart", () => {
|
|
96
|
+
return {
|
|
97
|
+
__esModule: true,
|
|
98
|
+
default: (props: LineChartStubProps): React.ReactElement => {
|
|
99
|
+
lineChartRenderMock(props);
|
|
100
|
+
return React.createElement(
|
|
101
|
+
"div",
|
|
102
|
+
{ "data-testid": "line-chart" },
|
|
103
|
+
`points:${props.data[0]?.data.length ?? 0}`,
|
|
104
|
+
);
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
import DashboardSloComponentElement from "../../../../App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardSloComponent";
|
|
110
|
+
import DashboardTextComponentElement from "../../../../App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardTextComponent";
|
|
111
|
+
import { DashboardBaseComponentProps } from "../../../../App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardBaseComponent";
|
|
112
|
+
import ServiceLevelObjective from "../../../Models/DatabaseModels/ServiceLevelObjective";
|
|
113
|
+
import AggregatedResult from "../../../Types/BaseDatabase/AggregatedResult";
|
|
114
|
+
import InBetween from "../../../Types/BaseDatabase/InBetween";
|
|
115
|
+
import DashboardBaseComponent from "../../../Types/Dashboard/DashboardComponents/DashboardBaseComponent";
|
|
116
|
+
import DashboardSloComponent, {
|
|
117
|
+
SloWidgetDisplayType,
|
|
118
|
+
SloWidgetMetric,
|
|
119
|
+
} from "../../../Types/Dashboard/DashboardComponents/DashboardSloComponent";
|
|
120
|
+
import DashboardTextComponent from "../../../Types/Dashboard/DashboardComponents/DashboardTextComponent";
|
|
121
|
+
import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType";
|
|
122
|
+
import {
|
|
123
|
+
GetHeightOfDashboardComponent,
|
|
124
|
+
GetWidthOfDashboardComponent,
|
|
125
|
+
} from "../../../Types/Dashboard/DashboardSize";
|
|
126
|
+
import {
|
|
127
|
+
DashboardTemplateType,
|
|
128
|
+
getTemplateConfig,
|
|
129
|
+
} from "../../../Types/Dashboard/DashboardTemplates";
|
|
130
|
+
import DashboardViewConfig from "../../../Types/Dashboard/DashboardViewConfig";
|
|
131
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
132
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
133
|
+
import SloStatus from "../../../Types/ServiceLevelObjective/SloStatus";
|
|
134
|
+
import RangeStartAndEndDateTime from "../../../Types/Time/RangeStartAndEndDateTime";
|
|
135
|
+
import TimeRange from "../../../Types/Time/TimeRange";
|
|
136
|
+
import { SLO_NOT_EVALUATED_TEXT } from "../../../Utils/Slo/SloWidgetFormat";
|
|
137
|
+
import ChartReferenceLineProps from "../../../UI/Components/Charts/Types/ReferenceLineProps";
|
|
138
|
+
import SeriesPoint from "../../../UI/Components/Charts/Types/SeriesPoints";
|
|
139
|
+
|
|
140
|
+
interface LineChartStubProps {
|
|
141
|
+
data: Array<SeriesPoint>;
|
|
142
|
+
referenceLines?: Array<ChartReferenceLineProps> | undefined;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ── the template under test ───────────────────────────────────────────────
|
|
146
|
+
|
|
147
|
+
const TEMPLATE_CONFIG: DashboardViewConfig | null = getTemplateConfig(
|
|
148
|
+
DashboardTemplateType.Slo,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
/*
|
|
152
|
+
* Cast rather than guarded at every use: "the SLO template resolves to a
|
|
153
|
+
* config at all" is asserted by the first test, which fails loudly before any
|
|
154
|
+
* render assertion can fail confusingly.
|
|
155
|
+
*/
|
|
156
|
+
const VIEW_CONFIG: DashboardViewConfig = TEMPLATE_CONFIG as DashboardViewConfig;
|
|
157
|
+
|
|
158
|
+
const TEMPLATE_COMPONENTS: Array<DashboardBaseComponent> =
|
|
159
|
+
TEMPLATE_CONFIG?.components || [];
|
|
160
|
+
|
|
161
|
+
const SLO_WIDGETS: Array<DashboardSloComponent> = TEMPLATE_COMPONENTS.filter(
|
|
162
|
+
(component: DashboardBaseComponent): boolean => {
|
|
163
|
+
return component.componentType === DashboardComponentType.Slo;
|
|
164
|
+
},
|
|
165
|
+
) as unknown as Array<DashboardSloComponent>;
|
|
166
|
+
|
|
167
|
+
const TEXT_WIDGETS: Array<DashboardTextComponent> = TEMPLATE_COMPONENTS.filter(
|
|
168
|
+
(component: DashboardBaseComponent): boolean => {
|
|
169
|
+
return component.componentType === DashboardComponentType.Text;
|
|
170
|
+
},
|
|
171
|
+
) as unknown as Array<DashboardTextComponent>;
|
|
172
|
+
|
|
173
|
+
const TILE_WIDGETS: Array<DashboardSloComponent> = SLO_WIDGETS.filter(
|
|
174
|
+
(widget: DashboardSloComponent): boolean => {
|
|
175
|
+
return widget.arguments.displayType === SloWidgetDisplayType.Tile;
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const CHART_WIDGETS: Array<DashboardSloComponent> = SLO_WIDGETS.filter(
|
|
180
|
+
(widget: DashboardSloComponent): boolean => {
|
|
181
|
+
return widget.arguments.displayType === SloWidgetDisplayType.Chart;
|
|
182
|
+
},
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
/** The widget's own label in a failure message — ids regenerate every call. */
|
|
186
|
+
type GetWidgetLabelFunction = (widget: DashboardSloComponent) => string;
|
|
187
|
+
|
|
188
|
+
const getWidgetLabel: GetWidgetLabelFunction = (
|
|
189
|
+
widget: DashboardSloComponent,
|
|
190
|
+
): string => {
|
|
191
|
+
return widget.arguments.widgetTitle || "(untitled SLO widget)";
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
type GetWidgetMetricFunction = (
|
|
195
|
+
widget: DashboardSloComponent,
|
|
196
|
+
) => SloWidgetMetric;
|
|
197
|
+
|
|
198
|
+
const getWidgetMetric: GetWidgetMetricFunction = (
|
|
199
|
+
widget: DashboardSloComponent,
|
|
200
|
+
): SloWidgetMetric => {
|
|
201
|
+
// Sli is the renderer's own fallback when the argument was never set.
|
|
202
|
+
return widget.arguments.sloMetric || SloWidgetMetric.Sli;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// ── fixtures ──────────────────────────────────────────────────────────────
|
|
206
|
+
|
|
207
|
+
const SLO_ID: ObjectID = new ObjectID("33333333-3333-4333-8333-333333333333");
|
|
208
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
209
|
+
"44444444-4444-4444-8444-444444444444",
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
/*
|
|
213
|
+
* A CUSTOM range pins the chart window to fixed instants; a relative range
|
|
214
|
+
* would resolve against the wall clock on every render.
|
|
215
|
+
*/
|
|
216
|
+
const START_DATE: Date = new Date("2026-08-10T00:00:00.000Z");
|
|
217
|
+
const END_DATE: Date = new Date("2026-08-10T06:00:00.000Z");
|
|
218
|
+
|
|
219
|
+
const DASHBOARD_RANGE: RangeStartAndEndDateTime = {
|
|
220
|
+
range: TimeRange.CUSTOM,
|
|
221
|
+
startAndEndDate: new InBetween<Date>(START_DATE, END_DATE),
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/*
|
|
225
|
+
* The dashboard canvas is twelve units wide, so this is the width a real
|
|
226
|
+
* board is laid out against; the helpers below turn each widget's DECLARED
|
|
227
|
+
* units into the pixel box the canvas would give it.
|
|
228
|
+
*/
|
|
229
|
+
const TOTAL_DASHBOARD_WIDTH_IN_PX: number = 1200;
|
|
230
|
+
|
|
231
|
+
const SLO_NAME: string = "Checkout availability";
|
|
232
|
+
const TARGET_PERCENTAGE: number = 99.9;
|
|
233
|
+
const SLI_PERCENTAGE: number = 99.95;
|
|
234
|
+
const BUDGET_REMAINING_PERCENTAGE: number = 42.5;
|
|
235
|
+
const BUDGET_REMAINING_SECONDS: number = 3600;
|
|
236
|
+
const BURN_RATE: number = 1.25;
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* What each tile must render for the row above. Written out rather than
|
|
240
|
+
* computed so a change in the formatter's rounding or units fails here:
|
|
241
|
+
* the SLI keeps three decimals, the budget percentage one, the budget
|
|
242
|
+
* seconds collapse to whole minutes (3600s -> 60 min) and burn rate is a
|
|
243
|
+
* multiplier.
|
|
244
|
+
*
|
|
245
|
+
* "×" is U+00D7 MULTIPLICATION SIGN, spelled as an escape so a mangled
|
|
246
|
+
* file encoding cannot make this pass by accident.
|
|
247
|
+
*/
|
|
248
|
+
interface TileExpectation {
|
|
249
|
+
value: string;
|
|
250
|
+
subline: string | null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const EXPECTED_TILE: Record<SloWidgetMetric, TileExpectation> = {
|
|
254
|
+
[SloWidgetMetric.Sli]: {
|
|
255
|
+
value: "99.95%",
|
|
256
|
+
subline: "target 99.9%",
|
|
257
|
+
},
|
|
258
|
+
[SloWidgetMetric.ErrorBudgetRemaining]: {
|
|
259
|
+
value: "42.5%",
|
|
260
|
+
subline: "60 min remaining",
|
|
261
|
+
},
|
|
262
|
+
[SloWidgetMetric.BurnRate]: {
|
|
263
|
+
value: "1.25×",
|
|
264
|
+
subline: null,
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
/** The renderer's own copy of these strings; neither is exported. */
|
|
269
|
+
const SETUP_MESSAGE: string = "Click to select an SLO";
|
|
270
|
+
const EMPTY_HISTORY_MESSAGE: RegExp = /No history for the selected/i;
|
|
271
|
+
|
|
272
|
+
type BuildSloFunction = (data?: {
|
|
273
|
+
hasTarget?: boolean | undefined;
|
|
274
|
+
}) => ServiceLevelObjective;
|
|
275
|
+
|
|
276
|
+
const buildSlo: BuildSloFunction = (
|
|
277
|
+
data: { hasTarget?: boolean | undefined } = {},
|
|
278
|
+
): ServiceLevelObjective => {
|
|
279
|
+
const slo: ServiceLevelObjective = new ServiceLevelObjective();
|
|
280
|
+
slo.name = SLO_NAME;
|
|
281
|
+
slo.currentSliPercentage = SLI_PERCENTAGE;
|
|
282
|
+
slo.errorBudgetRemainingPercentage = BUDGET_REMAINING_PERCENTAGE;
|
|
283
|
+
slo.errorBudgetRemainingSeconds = BUDGET_REMAINING_SECONDS;
|
|
284
|
+
slo.currentBurnRate = BURN_RATE;
|
|
285
|
+
slo.sloStatus = SloStatus.Healthy;
|
|
286
|
+
|
|
287
|
+
/*
|
|
288
|
+
* `targetPercentage` is nullable on the model, so leaving it unset is a
|
|
289
|
+
* state a real SLO can be in — and the reference-line rule turns on it.
|
|
290
|
+
*/
|
|
291
|
+
if (data.hasTarget !== false) {
|
|
292
|
+
slo.targetPercentage = TARGET_PERCENTAGE;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return slo;
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* An SLO the evaluation worker has not reached yet. The target is set at
|
|
300
|
+
* creation time, but every state column it maintains is empty — as NULL from
|
|
301
|
+
* Postgres, or absent altogether once a JSON round-trip drops it, which is
|
|
302
|
+
* why both shapes are exercised.
|
|
303
|
+
*/
|
|
304
|
+
type BuildUnevaluatedSloFunction = (
|
|
305
|
+
stateValue: null | undefined,
|
|
306
|
+
) => ServiceLevelObjective;
|
|
307
|
+
|
|
308
|
+
const buildUnevaluatedSlo: BuildUnevaluatedSloFunction = (
|
|
309
|
+
stateValue: null | undefined,
|
|
310
|
+
): ServiceLevelObjective => {
|
|
311
|
+
const slo: ServiceLevelObjective = new ServiceLevelObjective();
|
|
312
|
+
slo.name = SLO_NAME;
|
|
313
|
+
slo.targetPercentage = TARGET_PERCENTAGE;
|
|
314
|
+
|
|
315
|
+
const emptyState: Record<string, null | undefined> = {
|
|
316
|
+
currentSliPercentage: stateValue,
|
|
317
|
+
errorBudgetRemainingPercentage: stateValue,
|
|
318
|
+
errorBudgetRemainingSeconds: stateValue,
|
|
319
|
+
currentBurnRate: stateValue,
|
|
320
|
+
sloStatus: stateValue,
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
return Object.assign(slo, emptyState) as unknown as ServiceLevelObjective;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
/** One SloHistory bucket every five minutes, oldest first. */
|
|
327
|
+
type BuildSloHistoryFunction = (rowCount: number) => AggregatedResult;
|
|
328
|
+
|
|
329
|
+
const buildSloHistory: BuildSloHistoryFunction = (
|
|
330
|
+
rowCount: number,
|
|
331
|
+
): AggregatedResult => {
|
|
332
|
+
const rows: Array<JSONObject> = [];
|
|
333
|
+
|
|
334
|
+
for (let index: number = 0; index < rowCount; index++) {
|
|
335
|
+
rows.push({
|
|
336
|
+
timestamp: new Date(
|
|
337
|
+
START_DATE.getTime() + index * 5 * 60 * 1000,
|
|
338
|
+
).toISOString(),
|
|
339
|
+
value: 99.9 - index * 0.01,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return { data: rows } as unknown as AggregatedResult;
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const HISTORY_ROW_COUNT: number = 8;
|
|
347
|
+
|
|
348
|
+
// ── rendering ─────────────────────────────────────────────────────────────
|
|
349
|
+
|
|
350
|
+
type BuildPropsFunction = (
|
|
351
|
+
component: DashboardBaseComponent,
|
|
352
|
+
) => DashboardBaseComponentProps;
|
|
353
|
+
|
|
354
|
+
const buildBaseProps: BuildPropsFunction = (
|
|
355
|
+
component: DashboardBaseComponent,
|
|
356
|
+
): DashboardBaseComponentProps => {
|
|
357
|
+
/*
|
|
358
|
+
* Size every widget the way the canvas does — from the units the TEMPLATE
|
|
359
|
+
* declares — so the renderers' height-dependent branches (the Text widget
|
|
360
|
+
* scales its font to its row height, the chart reserves rows out of its
|
|
361
|
+
* tile) see the geometry the template actually ships rather than an
|
|
362
|
+
* arbitrary test number. A widget shrunk to a height-1 row in the template
|
|
363
|
+
* would then be exercised at that height here.
|
|
364
|
+
*/
|
|
365
|
+
return {
|
|
366
|
+
componentId: component.componentId,
|
|
367
|
+
isEditMode: false,
|
|
368
|
+
isSelected: false,
|
|
369
|
+
key: component.componentId.toString(),
|
|
370
|
+
onComponentUpdate: (): void => {
|
|
371
|
+
// No widget on this template writes back through this.
|
|
372
|
+
},
|
|
373
|
+
totalCurrentDashboardWidthInPx: TOTAL_DASHBOARD_WIDTH_IN_PX,
|
|
374
|
+
dashboardCanvasTopInPx: 0,
|
|
375
|
+
dashboardCanvasLeftInPx: 0,
|
|
376
|
+
dashboardCanvasWidthInPx: TOTAL_DASHBOARD_WIDTH_IN_PX,
|
|
377
|
+
dashboardCanvasHeightInPx: 800,
|
|
378
|
+
dashboardComponentHeightInPx: GetHeightOfDashboardComponent(
|
|
379
|
+
component.heightInDashboardUnits,
|
|
380
|
+
TOTAL_DASHBOARD_WIDTH_IN_PX,
|
|
381
|
+
),
|
|
382
|
+
dashboardComponentWidthInPx: GetWidthOfDashboardComponent(
|
|
383
|
+
component.widthInDashboardUnits,
|
|
384
|
+
TOTAL_DASHBOARD_WIDTH_IN_PX,
|
|
385
|
+
),
|
|
386
|
+
dashboardViewConfig: VIEW_CONFIG,
|
|
387
|
+
dashboardStartAndEndDate: DASHBOARD_RANGE,
|
|
388
|
+
metricTypes: [],
|
|
389
|
+
refreshTick: 0,
|
|
390
|
+
variables: undefined,
|
|
391
|
+
};
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
type RenderSloWidgetFunction = (widget: DashboardSloComponent) => RenderResult;
|
|
395
|
+
|
|
396
|
+
const renderSloWidget: RenderSloWidgetFunction = (
|
|
397
|
+
widget: DashboardSloComponent,
|
|
398
|
+
): RenderResult => {
|
|
399
|
+
return render(
|
|
400
|
+
<DashboardSloComponentElement
|
|
401
|
+
{...buildBaseProps(widget)}
|
|
402
|
+
component={widget}
|
|
403
|
+
/>,
|
|
404
|
+
);
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
type RenderTextWidgetFunction = (
|
|
408
|
+
widget: DashboardTextComponent,
|
|
409
|
+
) => RenderResult;
|
|
410
|
+
|
|
411
|
+
const renderTextWidget: RenderTextWidgetFunction = (
|
|
412
|
+
widget: DashboardTextComponent,
|
|
413
|
+
): RenderResult => {
|
|
414
|
+
return render(
|
|
415
|
+
<DashboardTextComponentElement
|
|
416
|
+
{...buildBaseProps(widget)}
|
|
417
|
+
component={widget}
|
|
418
|
+
/>,
|
|
419
|
+
);
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Picking an objective in the settings panel writes exactly one argument
|
|
424
|
+
* onto the stored widget. Cloned rather than mutated so the template's own
|
|
425
|
+
* components stay unconfigured for every other test in this file.
|
|
426
|
+
*/
|
|
427
|
+
type ConfigureSloWidgetFunction = (
|
|
428
|
+
widget: DashboardSloComponent,
|
|
429
|
+
) => DashboardSloComponent;
|
|
430
|
+
|
|
431
|
+
const configureSloWidget: ConfigureSloWidgetFunction = (
|
|
432
|
+
widget: DashboardSloComponent,
|
|
433
|
+
): DashboardSloComponent => {
|
|
434
|
+
return {
|
|
435
|
+
...widget,
|
|
436
|
+
arguments: {
|
|
437
|
+
...widget.arguments,
|
|
438
|
+
serviceLevelObjectiveId: SLO_ID.toString(),
|
|
439
|
+
},
|
|
440
|
+
};
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
/*
|
|
444
|
+
* Assertions carry the widget's title on both sides so a failure names the
|
|
445
|
+
* offending widget rather than reporting `false !== true` for one of six
|
|
446
|
+
* identical-looking renders.
|
|
447
|
+
*/
|
|
448
|
+
type ExpectRenderedFunction = (data: {
|
|
449
|
+
label: string;
|
|
450
|
+
text: string | RegExp;
|
|
451
|
+
}) => Promise<void>;
|
|
452
|
+
|
|
453
|
+
const expectRendered: ExpectRenderedFunction = async (data: {
|
|
454
|
+
label: string;
|
|
455
|
+
text: string | RegExp;
|
|
456
|
+
}): Promise<void> => {
|
|
457
|
+
await waitFor((): void => {
|
|
458
|
+
const isRendered: boolean = screen.queryAllByText(data.text).length > 0;
|
|
459
|
+
expect(
|
|
460
|
+
`${data.label}: ${isRendered ? "renders" : "does not render"} "${String(data.text)}"`,
|
|
461
|
+
).toBe(`${data.label}: renders "${String(data.text)}"`);
|
|
462
|
+
});
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
type ExpectNotRenderedFunction = (data: {
|
|
466
|
+
label: string;
|
|
467
|
+
text: string | RegExp;
|
|
468
|
+
}) => void;
|
|
469
|
+
|
|
470
|
+
const expectNotRendered: ExpectNotRenderedFunction = (data: {
|
|
471
|
+
label: string;
|
|
472
|
+
text: string | RegExp;
|
|
473
|
+
}): void => {
|
|
474
|
+
const isRendered: boolean = screen.queryAllByText(data.text).length > 0;
|
|
475
|
+
expect(
|
|
476
|
+
`${data.label}: ${isRendered ? "renders" : "does not render"} "${String(data.text)}"`,
|
|
477
|
+
).toBe(`${data.label}: does not render "${String(data.text)}"`);
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
/** Requests the widget under test issued, whichever route it reached for. */
|
|
481
|
+
type CountRequestsFunction = () => number;
|
|
482
|
+
|
|
483
|
+
const countRequests: CountRequestsFunction = (): number => {
|
|
484
|
+
return (
|
|
485
|
+
getItemMock.mock.calls.length +
|
|
486
|
+
getListMock.mock.calls.length +
|
|
487
|
+
aggregateMock.mock.calls.length
|
|
488
|
+
);
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
type GetLastChartPropsFunction = () => LineChartStubProps;
|
|
492
|
+
|
|
493
|
+
const getLastChartProps: GetLastChartPropsFunction = (): LineChartStubProps => {
|
|
494
|
+
const calls: Array<Array<unknown>> = lineChartRenderMock.mock
|
|
495
|
+
.calls as unknown as Array<Array<unknown>>;
|
|
496
|
+
|
|
497
|
+
return calls[calls.length - 1]![0] as LineChartStubProps;
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
beforeEach((): void => {
|
|
501
|
+
jest.clearAllMocks();
|
|
502
|
+
getCurrentProjectIdMock.mockReturnValue(PROJECT_ID);
|
|
503
|
+
getItemMock.mockResolvedValue(buildSlo());
|
|
504
|
+
getListMock.mockResolvedValue({ data: [], count: 0, skip: 0, limit: 1 });
|
|
505
|
+
aggregateMock.mockResolvedValue(buildSloHistory(HISTORY_ROW_COUNT));
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
afterEach((): void => {
|
|
509
|
+
cleanup();
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
describe("SLO dashboard template — what it ships", () => {
|
|
513
|
+
test("resolves to a config carrying SLO widgets in both display types", () => {
|
|
514
|
+
/*
|
|
515
|
+
* Every loop below iterates one of these arrays, so an empty one would
|
|
516
|
+
* make those tests pass vacuously for ever. This is the guard.
|
|
517
|
+
*/
|
|
518
|
+
expect(TEMPLATE_CONFIG).not.toBeNull();
|
|
519
|
+
expect(SLO_WIDGETS.length).toBeGreaterThan(0);
|
|
520
|
+
expect(TEXT_WIDGETS.length).toBeGreaterThan(0);
|
|
521
|
+
expect(TILE_WIDGETS.length).toBeGreaterThan(0);
|
|
522
|
+
expect(CHART_WIDGETS.length).toBeGreaterThan(0);
|
|
523
|
+
|
|
524
|
+
/*
|
|
525
|
+
* A widget whose displayType was dropped would fall out of BOTH groups
|
|
526
|
+
* and be silently skipped by the display-type tests.
|
|
527
|
+
*/
|
|
528
|
+
expect(TILE_WIDGETS.length + CHART_WIDGETS.length).toBe(SLO_WIDGETS.length);
|
|
529
|
+
|
|
530
|
+
/*
|
|
531
|
+
* The premise of the setup-state tests: a template cannot know a
|
|
532
|
+
* project's SLO ids, so it ships none. If this ever changes, the widget
|
|
533
|
+
* renders data instead of its setup state and the tests below become
|
|
534
|
+
* meaningless rather than failing for a good reason.
|
|
535
|
+
*/
|
|
536
|
+
for (const widget of SLO_WIDGETS) {
|
|
537
|
+
const label: string = getWidgetLabel(widget);
|
|
538
|
+
expect(
|
|
539
|
+
`${label}: ${widget.arguments.serviceLevelObjectiveId || "no objective"}`,
|
|
540
|
+
).toBe(`${label}: no objective`);
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
describe("SLO dashboard template — unconfigured widgets", () => {
|
|
546
|
+
test("every SLO widget renders its own title in the setup state and queries nothing", async () => {
|
|
547
|
+
expect(SLO_WIDGETS.length).toBeGreaterThan(0);
|
|
548
|
+
|
|
549
|
+
for (const widget of SLO_WIDGETS) {
|
|
550
|
+
const label: string = getWidgetLabel(widget);
|
|
551
|
+
const requestsBefore: number = countRequests();
|
|
552
|
+
|
|
553
|
+
renderSloWidget(widget);
|
|
554
|
+
|
|
555
|
+
await expectRendered({ label: label, text: SETUP_MESSAGE });
|
|
556
|
+
|
|
557
|
+
/*
|
|
558
|
+
* The title is what makes six identical placeholders tell the reader
|
|
559
|
+
* which tile is which before anything is configured — the reason the
|
|
560
|
+
* template sets widgetTitle on every one of them.
|
|
561
|
+
*/
|
|
562
|
+
await expectRendered({ label: label, text: label });
|
|
563
|
+
|
|
564
|
+
/*
|
|
565
|
+
* A widget with no objective must not reach ANY endpoint: on a public
|
|
566
|
+
* dashboard the stored id is the authorization decision, so a request
|
|
567
|
+
* without one has nothing the server could scope.
|
|
568
|
+
*/
|
|
569
|
+
expect(`${label}: ${countRequests() - requestsBefore} requests`).toBe(
|
|
570
|
+
`${label}: 0 requests`,
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
cleanup();
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
test("an unconfigured Tile offers setup rather than claiming the SLO is unevaluated", async () => {
|
|
578
|
+
expect(TILE_WIDGETS.length).toBeGreaterThan(0);
|
|
579
|
+
|
|
580
|
+
for (const widget of TILE_WIDGETS) {
|
|
581
|
+
const label: string = getWidgetLabel(widget);
|
|
582
|
+
|
|
583
|
+
renderSloWidget(widget);
|
|
584
|
+
|
|
585
|
+
await expectRendered({ label: label, text: SETUP_MESSAGE });
|
|
586
|
+
|
|
587
|
+
/*
|
|
588
|
+
* Two different empty states that must not be confused: "nothing is
|
|
589
|
+
* chosen" is the reader's next action, "not evaluated yet" is a claim
|
|
590
|
+
* about an SLO — and there is no SLO here to make it about.
|
|
591
|
+
*/
|
|
592
|
+
expectNotRendered({ label: label, text: SLO_NOT_EVALUATED_TEXT });
|
|
593
|
+
|
|
594
|
+
cleanup();
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
test("an unconfigured Chart offers setup rather than mounting an empty chart", async () => {
|
|
599
|
+
expect(CHART_WIDGETS.length).toBeGreaterThan(0);
|
|
600
|
+
|
|
601
|
+
for (const widget of CHART_WIDGETS) {
|
|
602
|
+
const label: string = getWidgetLabel(widget);
|
|
603
|
+
const chartsBefore: number = lineChartRenderMock.mock.calls.length;
|
|
604
|
+
|
|
605
|
+
renderSloWidget(widget);
|
|
606
|
+
|
|
607
|
+
await expectRendered({ label: label, text: SETUP_MESSAGE });
|
|
608
|
+
|
|
609
|
+
expect(
|
|
610
|
+
`${label}: ${lineChartRenderMock.mock.calls.length - chartsBefore} charts mounted`,
|
|
611
|
+
).toBe(`${label}: 0 charts mounted`);
|
|
612
|
+
|
|
613
|
+
cleanup();
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
test("reaches the setup state even before a project is resolved", async () => {
|
|
618
|
+
/*
|
|
619
|
+
* The unconfigured branch returns before the project check, so a board
|
|
620
|
+
* opened while the session's project is still unresolved shows the
|
|
621
|
+
* reader what to do instead of the "No project selected." error.
|
|
622
|
+
*/
|
|
623
|
+
getCurrentProjectIdMock.mockReturnValue(null);
|
|
624
|
+
|
|
625
|
+
for (const widget of SLO_WIDGETS) {
|
|
626
|
+
const label: string = getWidgetLabel(widget);
|
|
627
|
+
|
|
628
|
+
renderSloWidget(widget);
|
|
629
|
+
|
|
630
|
+
await expectRendered({ label: label, text: SETUP_MESSAGE });
|
|
631
|
+
expectNotRendered({ label: label, text: "No project selected." });
|
|
632
|
+
|
|
633
|
+
cleanup();
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
describe("SLO dashboard template — a configured Objective Health tile", () => {
|
|
639
|
+
test("each tile renders its own metric's number and subline", async () => {
|
|
640
|
+
expect(TILE_WIDGETS.length).toBeGreaterThan(0);
|
|
641
|
+
|
|
642
|
+
const coveredMetrics: Set<SloWidgetMetric> = new Set<SloWidgetMetric>();
|
|
643
|
+
|
|
644
|
+
for (const widget of TILE_WIDGETS) {
|
|
645
|
+
const label: string = getWidgetLabel(widget);
|
|
646
|
+
const metric: SloWidgetMetric = getWidgetMetric(widget);
|
|
647
|
+
const expected: TileExpectation = EXPECTED_TILE[metric];
|
|
648
|
+
|
|
649
|
+
coveredMetrics.add(metric);
|
|
650
|
+
|
|
651
|
+
renderSloWidget(configureSloWidget(widget));
|
|
652
|
+
|
|
653
|
+
await expectRendered({ label: label, text: expected.value });
|
|
654
|
+
|
|
655
|
+
if (expected.subline !== null) {
|
|
656
|
+
await expectRendered({ label: label, text: expected.subline });
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/*
|
|
660
|
+
* The three tiles read three different columns off the same row, so a
|
|
661
|
+
* tile wired to the wrong metric would still render a plausible
|
|
662
|
+
* number. Pin that each one renders ONLY its own.
|
|
663
|
+
*/
|
|
664
|
+
for (const otherMetric of Object.values(SloWidgetMetric)) {
|
|
665
|
+
if (otherMetric === metric) {
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
expectNotRendered({
|
|
670
|
+
label: label,
|
|
671
|
+
text: EXPECTED_TILE[otherMetric].value,
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
cleanup();
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/*
|
|
679
|
+
* The template is an SLO review in the order it is read — where the
|
|
680
|
+
* service is, how much room is left, how fast it is going — so all three
|
|
681
|
+
* numbers have to be on the board.
|
|
682
|
+
*/
|
|
683
|
+
expect(coveredMetrics.size).toBe(Object.keys(EXPECTED_TILE).length);
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
test.each([
|
|
687
|
+
["NULL state columns", null],
|
|
688
|
+
["absent state columns", undefined],
|
|
689
|
+
])(
|
|
690
|
+
"says the SLO is not evaluated yet for %s, never null or NaN",
|
|
691
|
+
async (_shape: string, stateValue: null | undefined) => {
|
|
692
|
+
getItemMock.mockResolvedValue(buildUnevaluatedSlo(stateValue));
|
|
693
|
+
|
|
694
|
+
expect(TILE_WIDGETS.length).toBeGreaterThan(0);
|
|
695
|
+
|
|
696
|
+
for (const widget of TILE_WIDGETS) {
|
|
697
|
+
const label: string = getWidgetLabel(widget);
|
|
698
|
+
|
|
699
|
+
const { container }: RenderResult = renderSloWidget(
|
|
700
|
+
configureSloWidget(widget),
|
|
701
|
+
);
|
|
702
|
+
|
|
703
|
+
await expectRendered({ label: label, text: SLO_NOT_EVALUATED_TEXT });
|
|
704
|
+
|
|
705
|
+
/*
|
|
706
|
+
* The whole reason the not-evaluated state exists: the worker's
|
|
707
|
+
* columns are empty until it first runs, and formatting one of them
|
|
708
|
+
* anyway renders "null%" / "NaN%" at tile size.
|
|
709
|
+
*/
|
|
710
|
+
const renderedText: string = container.textContent || "";
|
|
711
|
+
const leakedValue: RegExpMatchArray | null =
|
|
712
|
+
renderedText.match(/null|NaN|undefined/i);
|
|
713
|
+
|
|
714
|
+
expect(
|
|
715
|
+
`${label}: ${leakedValue ? leakedValue[0] : "no leaked value"}`,
|
|
716
|
+
).toBe(`${label}: no leaked value`);
|
|
717
|
+
|
|
718
|
+
// Nor any of the numbers an evaluated SLO would have rendered.
|
|
719
|
+
for (const metric of Object.values(SloWidgetMetric)) {
|
|
720
|
+
expectNotRendered({
|
|
721
|
+
label: label,
|
|
722
|
+
text: EXPECTED_TILE[metric].value,
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
cleanup();
|
|
727
|
+
}
|
|
728
|
+
},
|
|
729
|
+
);
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
describe("SLO dashboard template — the Error Budget Trends charts", () => {
|
|
733
|
+
test("an empty SloHistory series renders the empty state, not a chart", async () => {
|
|
734
|
+
aggregateMock.mockResolvedValue(buildSloHistory(0));
|
|
735
|
+
|
|
736
|
+
expect(CHART_WIDGETS.length).toBeGreaterThan(0);
|
|
737
|
+
|
|
738
|
+
for (const widget of CHART_WIDGETS) {
|
|
739
|
+
const label: string = getWidgetLabel(widget);
|
|
740
|
+
const chartsBefore: number = lineChartRenderMock.mock.calls.length;
|
|
741
|
+
|
|
742
|
+
renderSloWidget(configureSloWidget(widget));
|
|
743
|
+
|
|
744
|
+
await expectRendered({ label: label, text: EMPTY_HISTORY_MESSAGE });
|
|
745
|
+
|
|
746
|
+
/*
|
|
747
|
+
* A chart mounted over zero points draws axes around nothing, which
|
|
748
|
+
* reads as a broken widget rather than as "the worker has not written
|
|
749
|
+
* anything inside this window yet".
|
|
750
|
+
*/
|
|
751
|
+
expect(
|
|
752
|
+
`${label}: ${lineChartRenderMock.mock.calls.length - chartsBefore} charts mounted`,
|
|
753
|
+
).toBe(`${label}: 0 charts mounted`);
|
|
754
|
+
|
|
755
|
+
cleanup();
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
test("every chart plots the history it was given", async () => {
|
|
760
|
+
expect(CHART_WIDGETS.length).toBeGreaterThan(0);
|
|
761
|
+
|
|
762
|
+
for (const widget of CHART_WIDGETS) {
|
|
763
|
+
const label: string = getWidgetLabel(widget);
|
|
764
|
+
|
|
765
|
+
renderSloWidget(configureSloWidget(widget));
|
|
766
|
+
|
|
767
|
+
await expectRendered({
|
|
768
|
+
label: label,
|
|
769
|
+
text: `points:${HISTORY_ROW_COUNT}`,
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
cleanup();
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
test("the SLI chart draws the objective's target as a reference line", async () => {
|
|
777
|
+
const sliChart: DashboardSloComponent | undefined = CHART_WIDGETS.find(
|
|
778
|
+
(widget: DashboardSloComponent): boolean => {
|
|
779
|
+
return getWidgetMetric(widget) === SloWidgetMetric.Sli;
|
|
780
|
+
},
|
|
781
|
+
);
|
|
782
|
+
|
|
783
|
+
/*
|
|
784
|
+
* "Are we above the line" is the question the Error Budget Trends row
|
|
785
|
+
* exists to answer at a glance, so the template must carry an SLI chart
|
|
786
|
+
* for this test to be about anything.
|
|
787
|
+
*/
|
|
788
|
+
expect(sliChart).toBeDefined();
|
|
789
|
+
|
|
790
|
+
renderSloWidget(configureSloWidget(sliChart as DashboardSloComponent));
|
|
791
|
+
|
|
792
|
+
await expectRendered({
|
|
793
|
+
label: "SLI chart",
|
|
794
|
+
text: `points:${HISTORY_ROW_COUNT}`,
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
const referenceLines: Array<ChartReferenceLineProps> =
|
|
798
|
+
getLastChartProps().referenceLines || [];
|
|
799
|
+
|
|
800
|
+
expect(referenceLines.length).toBe(1);
|
|
801
|
+
expect(referenceLines[0]!.value).toBe(TARGET_PERCENTAGE);
|
|
802
|
+
expect(referenceLines[0]!.label).toBe(`Target ${TARGET_PERCENTAGE}%`);
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
test("omits the target line when the SLO has no targetPercentage", async () => {
|
|
806
|
+
getItemMock.mockResolvedValue(buildSlo({ hasTarget: false }));
|
|
807
|
+
|
|
808
|
+
const sliChart: DashboardSloComponent | undefined = CHART_WIDGETS.find(
|
|
809
|
+
(widget: DashboardSloComponent): boolean => {
|
|
810
|
+
return getWidgetMetric(widget) === SloWidgetMetric.Sli;
|
|
811
|
+
},
|
|
812
|
+
);
|
|
813
|
+
|
|
814
|
+
expect(sliChart).toBeDefined();
|
|
815
|
+
|
|
816
|
+
renderSloWidget(configureSloWidget(sliChart as DashboardSloComponent));
|
|
817
|
+
|
|
818
|
+
/*
|
|
819
|
+
* The chart still has to draw — otherwise "no reference line" would be
|
|
820
|
+
* true because nothing rendered at all.
|
|
821
|
+
*/
|
|
822
|
+
await expectRendered({
|
|
823
|
+
label: "SLI chart without a target",
|
|
824
|
+
text: `points:${HISTORY_ROW_COUNT}`,
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
/*
|
|
828
|
+
* A line at 0 (or at NaN) would read as a target of zero percent, which
|
|
829
|
+
* is a reliability claim the SLO never made.
|
|
830
|
+
*/
|
|
831
|
+
expect(getLastChartProps().referenceLines || []).toEqual([]);
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
test("the budget and burn-rate charts never draw a target line", async () => {
|
|
835
|
+
const otherCharts: Array<DashboardSloComponent> = CHART_WIDGETS.filter(
|
|
836
|
+
(widget: DashboardSloComponent): boolean => {
|
|
837
|
+
return getWidgetMetric(widget) !== SloWidgetMetric.Sli;
|
|
838
|
+
},
|
|
839
|
+
);
|
|
840
|
+
|
|
841
|
+
expect(otherCharts.length).toBeGreaterThan(0);
|
|
842
|
+
|
|
843
|
+
for (const widget of otherCharts) {
|
|
844
|
+
const label: string = getWidgetLabel(widget);
|
|
845
|
+
|
|
846
|
+
renderSloWidget(configureSloWidget(widget));
|
|
847
|
+
|
|
848
|
+
await expectRendered({
|
|
849
|
+
label: label,
|
|
850
|
+
text: `points:${HISTORY_ROW_COUNT}`,
|
|
851
|
+
});
|
|
852
|
+
|
|
853
|
+
/*
|
|
854
|
+
* targetPercentage is a percentage of the SLI; drawn across a burn
|
|
855
|
+
* rate ("99.9x") or across remaining budget it is meaningless, and
|
|
856
|
+
* the SLO row carries one on every one of these renders.
|
|
857
|
+
*/
|
|
858
|
+
const referenceLines: Array<ChartReferenceLineProps> =
|
|
859
|
+
getLastChartProps().referenceLines || [];
|
|
860
|
+
|
|
861
|
+
expect(`${label}: ${referenceLines.length} reference lines`).toBe(
|
|
862
|
+
`${label}: 0 reference lines`,
|
|
863
|
+
);
|
|
864
|
+
|
|
865
|
+
cleanup();
|
|
866
|
+
}
|
|
867
|
+
});
|
|
868
|
+
});
|
|
869
|
+
|
|
870
|
+
describe("SLO dashboard template — the text rows", () => {
|
|
871
|
+
test("every text row renders its configured sentence in full", () => {
|
|
872
|
+
expect(TEXT_WIDGETS.length).toBeGreaterThan(0);
|
|
873
|
+
|
|
874
|
+
for (const widget of TEXT_WIDGETS) {
|
|
875
|
+
const text: string = widget.arguments.text;
|
|
876
|
+
const { container }: RenderResult = renderTextWidget(widget);
|
|
877
|
+
|
|
878
|
+
const rendered: HTMLElement | null = screen.queryByText(text);
|
|
879
|
+
|
|
880
|
+
expect(`"${text}" -> "${rendered?.textContent ?? ""}"`).toBe(
|
|
881
|
+
`"${text}" -> "${text}"`,
|
|
882
|
+
);
|
|
883
|
+
|
|
884
|
+
// The renderer's own placeholder for a row with nothing to say.
|
|
885
|
+
expect(container.textContent).not.toContain("No text configured");
|
|
886
|
+
|
|
887
|
+
/*
|
|
888
|
+
* Section headers are bold and the guidance row is not — the one
|
|
889
|
+
* visual cue that separates an instruction from a heading.
|
|
890
|
+
*/
|
|
891
|
+
const expectedWeight: string = widget.arguments.isBold
|
|
892
|
+
? "font-semibold"
|
|
893
|
+
: "font-normal";
|
|
894
|
+
|
|
895
|
+
expect(
|
|
896
|
+
`"${text}" -> ${rendered?.className.includes(expectedWeight) ? expectedWeight : rendered?.className}`,
|
|
897
|
+
).toBe(`"${text}" -> ${expectedWeight}`);
|
|
898
|
+
|
|
899
|
+
cleanup();
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
|
|
903
|
+
test("the guidance row renders the whole instruction at a legible size", () => {
|
|
904
|
+
/*
|
|
905
|
+
* Row 1 is the one instruction a reader needs on a freshly created SLO
|
|
906
|
+
* dashboard: every widget above is inert until an objective is picked,
|
|
907
|
+
* and the widgets' own "Click to select an SLO" does nothing in the view
|
|
908
|
+
* mode a template opens in. A clipped or empty render loses that.
|
|
909
|
+
*/
|
|
910
|
+
const guidance: DashboardTextComponent | undefined = TEXT_WIDGETS.find(
|
|
911
|
+
(widget: DashboardTextComponent): boolean => {
|
|
912
|
+
return widget.topInDashboardUnits === 1;
|
|
913
|
+
},
|
|
914
|
+
);
|
|
915
|
+
|
|
916
|
+
expect(guidance).toBeDefined();
|
|
917
|
+
|
|
918
|
+
const widget: DashboardTextComponent = guidance as DashboardTextComponent;
|
|
919
|
+
const text: string = widget.arguments.text;
|
|
920
|
+
|
|
921
|
+
renderTextWidget(widget);
|
|
922
|
+
|
|
923
|
+
const rendered: HTMLElement = screen.getByText(text);
|
|
924
|
+
|
|
925
|
+
// Rendered whole: not the first clause, not an ellipsis.
|
|
926
|
+
expect(rendered.textContent).toBe(text);
|
|
927
|
+
expect((rendered.textContent || "").length).toBe(text.length);
|
|
928
|
+
|
|
929
|
+
/*
|
|
930
|
+
* The Text widget scales its font to the row height. A height-1 row that
|
|
931
|
+
* resolved to 0 (or to a non-number) would render the sentence
|
|
932
|
+
* invisibly while every text assertion above still passed.
|
|
933
|
+
*/
|
|
934
|
+
const fontSizeInPx: number = Number.parseFloat(rendered.style.fontSize);
|
|
935
|
+
|
|
936
|
+
expect(Number.isFinite(fontSizeInPx)).toBe(true);
|
|
937
|
+
expect(fontSizeInPx).toBeGreaterThan(0);
|
|
938
|
+
expect(fontSizeInPx).toBeLessThanOrEqual(64);
|
|
939
|
+
});
|
|
940
|
+
});
|