@oneuptime/common 14.0.8 → 14.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (639) hide show
  1. package/Models/DatabaseModels/Index.ts +2 -0
  2. package/Models/DatabaseModels/KubernetesAiAgent.ts +364 -0
  3. package/Models/DatabaseModels/KubernetesCluster.ts +3 -3
  4. package/Models/DatabaseModels/Project.ts +55 -5
  5. package/Models/DatabaseModels/ProxmoxResource.ts +49 -1
  6. package/Models/DatabaseModels/RunnerJob.ts +75 -0
  7. package/Models/DatabaseModels/TeamComplianceSetting.ts +143 -2
  8. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +17 -0
  9. package/Server/API/AIChatAPI.ts +6 -3
  10. package/Server/API/AIInvestigationAPI.ts +17 -10
  11. package/Server/API/AutoRemediationAPI.ts +207 -25
  12. package/Server/API/KubernetesClusterAiAccessAPI.ts +623 -21
  13. package/Server/API/MicrosoftTeamsAPI.ts +93 -14
  14. package/Server/API/ProxmoxResourceAPI.ts +244 -14
  15. package/Server/Infrastructure/GlobalCache.ts +32 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.ts +99 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.ts +137 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.ts +42 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  20. package/Server/Middleware/TelemetryIngest.ts +41 -18
  21. package/Server/Services/AIService.ts +70 -1
  22. package/Server/Services/AlertService.ts +352 -11
  23. package/Server/Services/AlertSeverityService.ts +65 -15
  24. package/Server/Services/AutoRemediationRuleService.ts +1 -1
  25. package/Server/Services/IncidentService.ts +280 -104
  26. package/Server/Services/IncidentSeverityService.ts +66 -15
  27. package/Server/Services/KubernetesAiAgentJobService.ts +185 -0
  28. package/Server/Services/KubernetesAiAgentService.ts +1634 -0
  29. package/Server/Services/KubernetesClusterAiAccessService.ts +1118 -451
  30. package/Server/Services/KubernetesClusterService.ts +129 -21
  31. package/Server/Services/ProjectService.ts +32 -0
  32. package/Server/Services/ProxmoxResourceService.ts +322 -5
  33. package/Server/Services/RunnerJobService.ts +241 -104
  34. package/Server/Services/RunnerService.ts +1 -1
  35. package/Server/Services/ScheduledMaintenanceService.ts +737 -1
  36. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +414 -56
  37. package/Server/Services/TeamComplianceSettingService.ts +1125 -9
  38. package/Server/Utils/AI/ClusterAccess/ClusterAccessContext.ts +67 -9
  39. package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +39 -10
  40. package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +14 -3
  41. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +37 -15
  42. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +67 -24
  43. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +48 -5
  44. package/Server/Utils/AI/SRE/IncidentPostmortemRunner.ts +40 -8
  45. package/Server/Utils/AI/SRE/InvestigationEligibility.ts +13 -2
  46. package/Server/Utils/AI/SRE/InvestigationGrader.ts +1 -1
  47. package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +6 -1
  48. package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +133 -7
  49. package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +58 -4
  50. package/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.ts +447 -0
  51. package/Server/Utils/Telemetry/ProxmoxNativePush.ts +903 -0
  52. package/Server/Utils/Telemetry/TelemetryEntity.ts +87 -27
  53. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +684 -47
  54. package/Tests/App/AdminDashboard/RowActionPlacementOverrides.test.tsx +278 -0
  55. package/Tests/App/Dashboard/AIChatChartWidgetZoom.test.tsx +738 -0
  56. package/Tests/App/Dashboard/AIFeaturesSettingsPointers.test.tsx +147 -0
  57. package/Tests/App/Dashboard/AIInsightsKubernetesClusterPage.test.tsx +1523 -0
  58. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +463 -3
  59. package/Tests/App/Dashboard/AffectedResourcesPickerDropdownPlacement.test.tsx +958 -0
  60. package/Tests/App/Dashboard/AffectedResourcesPickerFocusLeave.test.tsx +595 -0
  61. package/Tests/App/Dashboard/AskAiAvailability.test.ts +20 -3
  62. package/Tests/App/Dashboard/AskAiDisabled.test.tsx +8 -3
  63. package/Tests/App/Dashboard/CephRateChartReload.test.tsx +1456 -0
  64. package/Tests/App/Dashboard/CephTimeRangeZoom.test.tsx +1229 -0
  65. package/Tests/App/Dashboard/ChartCardTimeRangeZoom.test.tsx +151 -0
  66. package/Tests/App/Dashboard/ChartCardZoomAffordances.test.tsx +257 -0
  67. package/Tests/App/Dashboard/ChartRefetchFrame.test.tsx +141 -0
  68. package/Tests/App/Dashboard/ChartZoomHarness.tsx +249 -0
  69. package/Tests/App/Dashboard/ChartZoomStandIn.tsx +131 -0
  70. package/Tests/App/Dashboard/CloudServerlessSlowLoads.test.tsx +628 -0
  71. package/Tests/App/Dashboard/CloudServerlessTimeRangeZoom.test.tsx +607 -0
  72. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +91 -19
  73. package/Tests/App/Dashboard/CompanionMetricsTabZoom.test.tsx +632 -0
  74. package/Tests/App/Dashboard/ContainerChartZoomStandIn.tsx +195 -0
  75. package/Tests/App/Dashboard/ContainerHostOverviewSlowLoads.test.tsx +542 -0
  76. package/Tests/App/Dashboard/ContainerHostOverviewTimeRangeZoom.test.tsx +848 -0
  77. package/Tests/App/Dashboard/ContainerMetricsTimeRangeZoom.test.tsx +561 -0
  78. package/Tests/App/Dashboard/DashboardBoardWideZoomShell.test.tsx +1147 -0
  79. package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +3 -2
  80. package/Tests/App/Dashboard/DashboardHistogramWidgetDragCursor.test.tsx +399 -0
  81. package/Tests/App/Dashboard/DashboardHistogramWidgetZoom.test.tsx +985 -0
  82. package/Tests/App/Dashboard/DashboardHistogramWidgetZoomHint.test.tsx +803 -0
  83. package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +1 -0
  84. package/Tests/App/Dashboard/DashboardSettingsPreviewZoom.test.tsx +679 -0
  85. package/Tests/App/Dashboard/DashboardSloAndDataSourceChartZoom.test.tsx +881 -0
  86. package/Tests/App/Dashboard/DashboardTraceStatusWidgets.test.tsx +878 -0
  87. package/Tests/App/Dashboard/DatabaseMetricChartModalTimeRangeZoom.test.tsx +442 -0
  88. package/Tests/App/Dashboard/DatabaseOverviewTimeRangeZoom.test.tsx +831 -0
  89. package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +43 -0
  90. package/Tests/App/Dashboard/DockerSwarmInsightsTimeRangeZoom.test.tsx +524 -0
  91. package/Tests/App/Dashboard/DockerSwarmRateChartRefresh.test.tsx +259 -0
  92. package/Tests/App/Dashboard/EdgeDetailPanelHistory.test.tsx +763 -0
  93. package/Tests/App/Dashboard/EdgeDetailPanelTimeRangeZoom.test.tsx +547 -0
  94. package/Tests/App/Dashboard/EdgeHistoryBucketsCases.tsx +565 -0
  95. package/Tests/App/Dashboard/EdgeHistoryBucketsKathmandu.test.tsx +73 -0
  96. package/Tests/App/Dashboard/EdgeHistoryBucketsKolkata.test.tsx +74 -0
  97. package/Tests/App/Dashboard/EdgeHistoryBucketsNewYork.test.tsx +72 -0
  98. package/Tests/App/Dashboard/EdgeHistoryBucketsUtc.test.tsx +72 -0
  99. package/Tests/App/Dashboard/EmbeddedMetricCardRefresh.test.tsx +310 -0
  100. package/Tests/App/Dashboard/EmbeddedMetricCardTimeRangeZoom.test.tsx +536 -0
  101. package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +3 -1
  102. package/Tests/App/Dashboard/EscalationRuleRowActions.test.tsx +660 -0
  103. package/Tests/App/Dashboard/EventNotes.test.tsx +2 -2
  104. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +587 -13
  105. package/Tests/App/Dashboard/EventOverviewSnapshotExplorerZoom.test.tsx +1139 -0
  106. package/Tests/App/Dashboard/EventOverviewSnapshotZoomAcrossTabs.test.tsx +1057 -0
  107. package/Tests/App/Dashboard/EventOverviewTelemetrySnapshotZoom.test.tsx +757 -0
  108. package/Tests/App/Dashboard/ExceptionOccurrenceTrendZoom.test.tsx +675 -0
  109. package/Tests/App/Dashboard/ExceptionOccurrencesZoomSurvivesViewSwitch.test.tsx +405 -0
  110. package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +67 -3
  111. package/Tests/App/Dashboard/ExceptionTablesSpanStatus.test.tsx +515 -0
  112. package/Tests/App/Dashboard/ExplorerOwnZoomRegression.test.tsx +739 -0
  113. package/Tests/App/Dashboard/FlowBandwidthAxisCases.tsx +461 -0
  114. package/Tests/App/Dashboard/FlowBandwidthAxisKathmandu.test.tsx +25 -0
  115. package/Tests/App/Dashboard/FlowBandwidthAxisKolkata.test.tsx +25 -0
  116. package/Tests/App/Dashboard/FlowBandwidthAxisNewYork.test.tsx +25 -0
  117. package/Tests/App/Dashboard/FlowBandwidthAxisUtc.test.tsx +24 -0
  118. package/Tests/App/Dashboard/FlowTopTalkersZoomRefetch.test.tsx +722 -0
  119. package/Tests/App/Dashboard/FlowViewportGuard.test.tsx +2526 -0
  120. package/Tests/App/Dashboard/HostPagesSlowLoads.test.tsx +872 -0
  121. package/Tests/App/Dashboard/HostPagesTimeRangeZoom.test.tsx +1208 -0
  122. package/Tests/App/Dashboard/IncidentRootCauseTimeRangeZoom.test.tsx +358 -0
  123. package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +100 -9
  124. package/Tests/App/Dashboard/InfrastructureMetricsTabTimeRangeZoom.test.tsx +485 -0
  125. package/Tests/App/Dashboard/InvestigationDrawerCompanionZoom.test.tsx +655 -0
  126. package/Tests/App/Dashboard/InvestigationDrawerZoom.test.tsx +830 -0
  127. package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +338 -2
  128. package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +454 -16
  129. package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +799 -819
  130. package/Tests/App/Dashboard/KubernetesClusterAiAgentOverviewCard.test.tsx +367 -0
  131. package/Tests/App/Dashboard/KubernetesClusterAiAgentStatus.test.ts +1202 -0
  132. package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +106 -0
  133. package/Tests/App/Dashboard/KubernetesClusterAiNavigation.test.tsx +354 -0
  134. package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +1884 -2054
  135. package/Tests/App/Dashboard/KubernetesClusterAiPageServerParity.test.ts +478 -179
  136. package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +50 -0
  137. package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +2 -1
  138. package/Tests/App/Dashboard/KubernetesClusterOverviewZoom.test.tsx +1217 -0
  139. package/Tests/App/Dashboard/KubernetesClusterPagesZoom.test.tsx +731 -0
  140. package/Tests/App/Dashboard/KubernetesCostsLoadRecovery.test.tsx +869 -0
  141. package/Tests/App/Dashboard/KubernetesCostsZoom.test.tsx +1214 -0
  142. package/Tests/App/Dashboard/KubernetesCostsZoomExactHours.test.tsx +692 -0
  143. package/Tests/App/Dashboard/KubernetesNetworkThroughputReload.test.tsx +902 -0
  144. package/Tests/App/Dashboard/KubernetesNetworkZoomBucketEdges.test.tsx +571 -0
  145. package/Tests/App/Dashboard/KubernetesOverviewZoomBucketEdges.test.tsx +697 -0
  146. package/Tests/App/Dashboard/KubernetesResourceMetricsTabZoom.test.tsx +633 -0
  147. package/Tests/App/Dashboard/LogsExplorerTimeRangeZoom.test.tsx +470 -0
  148. package/Tests/App/Dashboard/LogsInsightsTimeRangeZoom.test.tsx +948 -0
  149. package/Tests/App/Dashboard/LogsViewerPinnedWindowZoom.test.tsx +486 -0
  150. package/Tests/App/Dashboard/MetricChartsBucketInspectorDoubleClick.test.tsx +1001 -0
  151. package/Tests/App/Dashboard/MetricExplorerInvestigationAutoRefresh.test.tsx +514 -0
  152. package/Tests/App/Dashboard/MetricExplorerSavedViewZoomRoundTrip.test.tsx +581 -0
  153. package/Tests/App/Dashboard/MetricExplorerTimeRangeZoom.test.tsx +1162 -0
  154. package/Tests/App/Dashboard/MetricMonitorPreviewZoomLabel.test.ts +72 -0
  155. package/Tests/App/Dashboard/MetricRowSparklineTimeRangeZoom.test.tsx +204 -0
  156. package/Tests/App/Dashboard/MetricViewFirstResultLands.test.tsx +408 -0
  157. package/Tests/App/Dashboard/MetricViewOwnZoomResetPlacement.test.tsx +952 -0
  158. package/Tests/App/Dashboard/MetricViewTimeRange.test.ts +139 -0
  159. package/Tests/App/Dashboard/MetricViewTimeRangeZoom.test.tsx +556 -0
  160. package/Tests/App/Dashboard/MonitorMetricsChartWrappersZoom.test.tsx +552 -0
  161. package/Tests/App/Dashboard/MonitorMetricsTabsTimeRangeZoom.test.tsx +740 -0
  162. package/Tests/App/Dashboard/MonitorOverviewChartsTimeRangeZoom.test.tsx +735 -0
  163. package/Tests/App/Dashboard/MonitorStepPreviewsTimeRangeZoom.test.tsx +835 -0
  164. package/Tests/App/Dashboard/NetworkDeviceTimeRangeZoom.test.tsx +1115 -0
  165. package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +186 -17
  166. package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +155 -46
  167. package/Tests/App/Dashboard/PasskeySettings.test.tsx +87 -2
  168. package/Tests/App/Dashboard/ProjectAISettingsPages.test.tsx +884 -0
  169. package/Tests/App/Dashboard/ProxmoxNodeRemove.test.tsx +621 -0
  170. package/Tests/App/Dashboard/ProxmoxOverviewSlowLoads.test.tsx +584 -0
  171. package/Tests/App/Dashboard/ProxmoxPagesTimeRangeZoom.test.tsx +823 -0
  172. package/Tests/App/Dashboard/ProxmoxRateChartReload.test.tsx +1253 -0
  173. package/Tests/App/Dashboard/PublicDashboardBoardWideZoom.test.tsx +605 -0
  174. package/Tests/App/Dashboard/RealRowsLineChart.tsx +250 -0
  175. package/Tests/App/Dashboard/RechartsHostsPlotCursor.test.tsx +513 -0
  176. package/Tests/App/Dashboard/RowActionPlacementOverrides.test.tsx +865 -0
  177. package/Tests/App/Dashboard/RumOverviewTimeRangeZoom.test.tsx +877 -0
  178. package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +20 -4
  179. package/Tests/App/Dashboard/RunnerSupersededByAiAgentNote.test.tsx +296 -0
  180. package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +146 -36
  181. package/Tests/App/Dashboard/ServiceDatabaseSlowLoads.test.tsx +1166 -0
  182. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +1243 -104
  183. package/Tests/App/Dashboard/ServiceOverviewTimeRangeZoom.test.tsx +792 -0
  184. package/Tests/App/Dashboard/SloBudgetBurnDownZoom.test.tsx +771 -0
  185. package/Tests/App/Dashboard/SloBudgetBurnDownZoomAffordances.test.tsx +380 -0
  186. package/Tests/App/Dashboard/SloEventMetricsBarChartZoom.test.tsx +369 -0
  187. package/Tests/App/Dashboard/SloHistoryChartsTimeRangeZoom.test.tsx +694 -0
  188. package/Tests/App/Dashboard/SloHistoryChartsZoomAffordances.test.tsx +497 -0
  189. package/Tests/App/Dashboard/SloMetricsTimeRangeZoom.test.tsx +541 -0
  190. package/Tests/App/Dashboard/SlowLoadHarness.ts +123 -0
  191. package/Tests/App/Dashboard/SnapshotExplorerPrimaryZoom.test.tsx +1194 -0
  192. package/Tests/App/Dashboard/SnapshotViewerPinnedWindow.test.tsx +620 -0
  193. package/Tests/App/Dashboard/TelemetrySnapshotPanelTimeRangeZoom.test.tsx +765 -0
  194. package/Tests/App/Dashboard/TelemetrySnapshotZoom.test.tsx +516 -0
  195. package/Tests/App/Dashboard/TelemetrySnapshotZoomAcrossTabs.test.tsx +827 -0
  196. package/Tests/App/Dashboard/TimeRangeZoomPageHarness.tsx +463 -0
  197. package/Tests/App/Dashboard/TraceChartEditorStatusSplit.test.tsx +543 -0
  198. package/Tests/App/Dashboard/TraceStatusPresentation.test.tsx +967 -0
  199. package/Tests/App/Dashboard/TraceTimelineMinimapZoom.test.tsx +315 -0
  200. package/Tests/App/Dashboard/TracesAnalyticsStatusSplit.test.tsx +778 -0
  201. package/Tests/App/Dashboard/TracesAnalyticsViewZoom.test.tsx +349 -0
  202. package/Tests/App/Dashboard/TracesExplorerTimeRangeZoom.test.tsx +551 -0
  203. package/Tests/App/Dashboard/TracesStatusChartAndFacet.test.tsx +687 -0
  204. package/Tests/App/Dashboard/TracesViewerStaleResponses.test.tsx +458 -0
  205. package/Tests/App/Dashboard/UptimeStripsExcludedFromZoom.test.tsx +406 -0
  206. package/Tests/App/Dashboard/VMwareOverviewSlowLoads.test.tsx +535 -0
  207. package/Tests/App/Dashboard/VMwarePagesTimeRangeZoom.test.tsx +606 -0
  208. package/Tests/App/Dashboard/ValueWidgetSparklineStaleHover.test.tsx +1292 -0
  209. package/Tests/App/Dashboard/ValueWidgetSparklineZoom.test.tsx +765 -0
  210. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +98 -0
  211. package/Tests/Models/DatabaseModels/KubernetesAiAgentModel.test.ts +295 -0
  212. package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +347 -0
  213. package/Tests/Server/API/AIChatRouteAuthorization.test.ts +58 -0
  214. package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +1 -1
  215. package/Tests/Server/API/AIInvestigationAPI.test.ts +123 -45
  216. package/Tests/Server/API/AutoRemediationApproveClusterRound.test.ts +1329 -0
  217. package/Tests/Server/API/AutoRemediationApproveKubectlRecheck.test.ts +25 -2
  218. package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -0
  219. package/Tests/Server/API/KubernetesClusterAiAccessAPIAgent.test.ts +903 -0
  220. package/Tests/Server/API/MicrosoftTeamsChatsRefreshRoute.test.ts +667 -0
  221. package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +294 -6
  222. package/Tests/Server/API/ProxmoxResourceAPIRemoveNode.test.ts +1932 -0
  223. package/Tests/Server/Infrastructure/GlobalCache.test.ts +195 -0
  224. package/Tests/Server/Infrastructure/Postgres/AddKubernetesAiAgentAndAiDefaultsMigration.test.ts +623 -0
  225. package/Tests/Server/Infrastructure/Postgres/AddKubernetesClusterAiAccessMigration.test.ts +87 -10
  226. package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleScopeMigration.test.ts +622 -0
  227. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +61 -4
  228. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +98 -2
  229. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +105 -2
  230. package/Tests/Server/Services/AIServiceBalanceBlocker.test.ts +282 -0
  231. package/Tests/Server/Services/AlertMonitorClearWritesNull.test.ts +409 -0
  232. package/Tests/Server/Services/AlertMonitorEditFeed.test.ts +474 -0
  233. package/Tests/Server/Services/AlertMonitorEditGuard.test.ts +610 -0
  234. package/Tests/Server/Services/AutoRemediationClusterRuleEngine.test.ts +2 -0
  235. package/Tests/Server/Services/AutoRemediationRuleCommandRunners.test.ts +2 -1
  236. package/Tests/Server/Services/IncidentAffectedMonitorsEdit.test.ts +1360 -0
  237. package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +3 -1
  238. package/Tests/Server/Services/IncidentSeverityDeletePausesComplianceRules.test.ts +488 -0
  239. package/Tests/Server/Services/KubernetesAiAgentJobService.test.ts +329 -0
  240. package/Tests/Server/Services/KubernetesAiAgentServiceHelpers.test.ts +618 -0
  241. package/Tests/Server/Services/KubernetesAiAgentServiceLifecycle.test.ts +1444 -0
  242. package/Tests/Server/Services/KubernetesAiAgentServiceRegister.test.ts +1666 -0
  243. package/Tests/Server/Services/KubernetesClusterAiAccessDeletedRunnerRemedy.test.ts +140 -111
  244. package/Tests/Server/Services/KubernetesClusterAiAccessGapNextSteps.test.ts +267 -105
  245. package/Tests/Server/Services/KubernetesClusterAiAccessLegacySuperseded.test.ts +440 -0
  246. package/Tests/Server/Services/KubernetesClusterAiAccessService.test.ts +567 -411
  247. package/Tests/Server/Services/KubernetesClusterAiAccessTarget.test.ts +1168 -0
  248. package/Tests/Server/Services/KubernetesClusterAiSettingsPermission.test.ts +410 -12
  249. package/Tests/Server/Services/KubernetesClusterServiceAiAccessFeed.test.ts +55 -0
  250. package/Tests/Server/Services/ProjectServiceNewProjectAiDefaults.test.ts +288 -0
  251. package/Tests/Server/Services/ProxmoxResourcePostgres.test.ts +5633 -0
  252. package/Tests/Server/Services/ProxmoxResourceService.test.ts +6458 -5
  253. package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +48 -15
  254. package/Tests/Server/Services/RunnerJobEnqueueKubectlAiAgent.test.ts +620 -0
  255. package/Tests/Server/Services/RunnerJobKubectlWriteScope.test.ts +170 -3
  256. package/Tests/Server/Services/RunnerJobTimeoutReason.test.ts +72 -0
  257. package/Tests/Server/Services/RunnerServiceAgentName.test.ts +6 -4
  258. package/Tests/Server/Services/ScheduledMaintenanceAttachmentEdit.test.ts +2113 -0
  259. package/Tests/Server/Services/ScheduledMaintenanceMonitorRelease.test.ts +972 -0
  260. package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +2237 -0
  261. package/Tests/Server/Services/TeamComplianceSettingService.test.ts +3988 -138
  262. package/Tests/Server/Utils/AI/ClusterAccessContext.test.ts +107 -1
  263. package/Tests/Server/Utils/AI/IncidentPostmortemRunner.test.ts +351 -0
  264. package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +2 -0
  265. package/Tests/Server/Utils/AI/InvestigationEligibility.test.ts +310 -0
  266. package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +70 -0
  267. package/Tests/Server/Utils/AI/KubectlJobRunnerFinishedJob.test.ts +58 -0
  268. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectl.test.ts +2 -0
  269. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectlOutcome.test.ts +2 -0
  270. package/Tests/Server/Utils/AI/RemediationCommandToolsLiveCluster.test.ts +2 -0
  271. package/Tests/Server/Utils/AI/RemediationCommandToolsRunnerScope.test.ts +125 -1
  272. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +252 -3
  273. package/Tests/Server/Utils/AI/RemediationExecutionRunnerClusterMode.test.ts +2 -0
  274. package/Tests/Server/Utils/AI/RemediationExecutionRunnerProjectGates.test.ts +240 -0
  275. package/Tests/Server/Utils/AI/RemediationKubectlCopyParity.test.ts +2 -0
  276. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +2 -0
  277. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorUnknownRun.test.ts +2 -0
  278. package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +2 -0
  279. package/Tests/Server/Utils/Telemetry/HostAssetAttributesFromOtlp.test.ts +68 -0
  280. package/Tests/Server/Utils/Telemetry/InventoryMirrorPostgres.test.ts +370 -0
  281. package/Tests/Server/Utils/Telemetry/NetworkDeviceInventoryAttributes.test.ts +522 -0
  282. package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +155 -0
  283. package/Tests/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.test.ts +8631 -0
  284. package/Tests/Server/Utils/Telemetry/ProxmoxNativePush.test.ts +2852 -0
  285. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +367 -1
  286. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +45 -3
  287. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +25 -0
  288. package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNames.test.ts +3119 -0
  289. package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNamesPostgres.test.ts +1721 -0
  290. package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +581 -113
  291. package/Tests/Types/Kubernetes/KubernetesAiAgentAccessContract.test.ts +510 -0
  292. package/Tests/Types/Team/ComplianceRule.test.ts +1029 -0
  293. package/Tests/Types/Team/TeamComplianceStatus.test.ts +176 -0
  294. package/Tests/UI/Components/ActionButton/RowActions.test.tsx +641 -0
  295. package/Tests/UI/Components/ActionButton/RowActionsAccessibility.test.tsx +414 -0
  296. package/Tests/UI/Components/ActionButton/SplitActionButtons.test.ts +565 -0
  297. package/Tests/UI/Components/Charts/BarChartDragToSelect.test.tsx +386 -0
  298. package/Tests/UI/Components/Charts/ChartDoubleClickResetWithoutDblclick.test.tsx +1025 -0
  299. package/Tests/UI/Components/Charts/ChartGroupPageZoomHint.test.tsx +196 -0
  300. package/Tests/UI/Components/Charts/ChartPlaceholdersTakeDoubleClick.test.tsx +1861 -0
  301. package/Tests/UI/Components/Charts/ChartPlotClicksWhileResetArmed.test.tsx +382 -0
  302. package/Tests/UI/Components/Charts/ChartRangeSelection.test.tsx +704 -0
  303. package/Tests/UI/Components/Charts/ChartRangeSelectionDoubleClickReset.test.tsx +1481 -0
  304. package/Tests/UI/Components/Charts/ChartRangeSelectionRealRecharts.test.tsx +918 -0
  305. package/Tests/UI/Components/Charts/ChartRowBucketStart.test.ts +350 -0
  306. package/Tests/UI/Components/Charts/DoubleClickReset.test.tsx +996 -0
  307. package/Tests/UI/Components/Charts/HistogramDoubleClickResetRealRecharts.test.tsx +965 -0
  308. package/Tests/UI/Components/Charts/HistogramDriftThenRefetch.test.tsx +277 -0
  309. package/Tests/UI/Components/Charts/HistogramRangeSelectionDataChange.test.tsx +1757 -0
  310. package/Tests/UI/Components/Charts/HistogramRangeSelectionRealRecharts.test.tsx +560 -0
  311. package/Tests/UI/Components/Charts/TimeRangeZoom/ChartPageTimeRangeZoom.test.tsx +513 -0
  312. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.test.tsx +845 -0
  313. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.test.tsx +119 -0
  314. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHintTailwind.test.tsx +274 -0
  315. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.test.ts +433 -0
  316. package/Tests/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.test.tsx +863 -0
  317. package/Tests/UI/Components/Charts/TimeRangeZoom/ZoomDocsPromises.test.tsx +1147 -0
  318. package/Tests/UI/Components/DisabledButtonTooltip.test.tsx +14 -3
  319. package/Tests/UI/Components/EntityDropdownEscape.test.tsx +454 -0
  320. package/Tests/UI/Components/EntityDropdownFocusLeave.test.tsx +420 -0
  321. package/Tests/UI/Components/Forms/FormFieldDropdownDisabled.test.tsx +233 -0
  322. package/Tests/UI/Components/Input.test.tsx +80 -1
  323. package/Tests/UI/Components/LogsAnalyticsViewZoom.test.tsx +947 -0
  324. package/Tests/UI/Components/LogsHistogramDragTooltip.test.tsx +17 -5
  325. package/Tests/UI/Components/LogsViewerAnalyticsZoom.test.tsx +501 -0
  326. package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +1 -1
  327. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +6 -4
  328. package/Tests/UI/Components/ModelTable/BaseModelTablePermissionGating.test.tsx +60 -8
  329. package/Tests/UI/Components/ModelTable/BaseModelTableRowActions.test.tsx +476 -0
  330. package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +7 -5
  331. package/Tests/UI/Components/MoreMenuPortal.test.tsx +623 -0
  332. package/Tests/UI/Components/StatusPage/ResourceGridActions.test.tsx +538 -0
  333. package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +14 -4
  334. package/Tests/UI/Components/TableCellWrapping.test.tsx +3 -3
  335. package/Tests/UI/Components/TableRowActions.test.tsx +472 -0
  336. package/Tests/UI/Components/TelemetryHistogramDragTooltip.test.tsx +1 -1
  337. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerHistogramClickZoom.test.tsx +1 -1
  338. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerZoomScope.test.tsx +470 -0
  339. package/Tests/UI/Components/TelemetryViewer/UseViewerTimeRangeZoom.test.tsx +571 -0
  340. package/Tests/UI/Components/TelemetryViewer/ViewerDoubleClickResetUnderDataChange.test.tsx +928 -0
  341. package/Tests/UI/Components/TelemetryViewer/ViewerFollowsEnclosingZoom.test.tsx +1569 -0
  342. package/Tests/UI/Components/Toggle.test.tsx +66 -0
  343. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardRefreshNames.test.tsx +1023 -0
  344. package/Tests/UI/Rum/ChunkLoader.test.ts +201 -0
  345. package/Tests/UI/Rum/FidelityNotices.test.ts +54 -0
  346. package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +72 -0
  347. package/Tests/UI/Rum/ReplayFrameCapture.test.ts +1009 -9
  348. package/Tests/UI/Rum/ReplayRecordedAssets.test.ts +1069 -0
  349. package/Tests/UI/Rum/ReplayStage.test.tsx +913 -2
  350. package/Tests/UI/Rum/SessionReplayTable.test.tsx +443 -8
  351. package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +439 -9
  352. package/Tests/UI/Rum/UserFlowTablesRowActions.test.tsx +501 -0
  353. package/Tests/Utils/AiRemediation/KubectlPolicyChartRbacParity.test.ts +47 -19
  354. package/Tests/Utils/AiRemediation/KubectlWriteScopeCallerParity.test.ts +2 -0
  355. package/Tests/Utils/AiRemediation/KubernetesAiAgentPolicyCopyParity.test.ts +396 -0
  356. package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +104 -1
  357. package/Types/AI/AIRunType.ts +9 -4
  358. package/Types/AI/InvestigationNotStartedReason.ts +6 -0
  359. package/Types/AutoRemediation/AiRemediationCommandPlan.ts +14 -16
  360. package/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.ts +28 -0
  361. package/Types/Dashboard/DashboardComponents/DashboardTraceChartComponent.ts +4 -2
  362. package/Types/Kubernetes/KubernetesClusterAiAccess.ts +263 -32
  363. package/Types/Kubernetes/KubernetesClusterAiAccessPermissions.ts +20 -16
  364. package/Types/Kubernetes/KubernetesClusterAiInsights.ts +81 -0
  365. package/Types/Monitor/ProxmoxAlertTemplates.ts +4 -4
  366. package/Types/Team/ComplianceNotificationChannel.ts +22 -0
  367. package/Types/Team/ComplianceRule.ts +434 -0
  368. package/Types/Team/ComplianceRuleType.ts +21 -0
  369. package/Types/Team/TeamComplianceStatus.ts +81 -0
  370. package/Types/Telemetry/TelemetryIngestSurface.ts +28 -0
  371. package/UI/Components/ActionButton/ActionButtonSchema.ts +21 -0
  372. package/UI/Components/ActionButton/RowActions.tsx +238 -0
  373. package/UI/Components/ActionButton/SplitActionButtons.ts +173 -0
  374. package/UI/Components/Charts/Area/AreaChart.tsx +32 -2
  375. package/UI/Components/Charts/Bar/BarChart.tsx +40 -3
  376. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +37 -11
  377. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +80 -243
  378. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +122 -31
  379. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +95 -244
  380. package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +214 -0
  381. package/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.ts +32 -0
  382. package/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.ts +599 -0
  383. package/UI/Components/Charts/Line/LineChart.tsx +32 -2
  384. package/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.tsx +70 -0
  385. package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.tsx +226 -0
  386. package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.tsx +73 -0
  387. package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.ts +163 -0
  388. package/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.ts +215 -0
  389. package/UI/Components/Charts/Utils/DataPoint.ts +20 -8
  390. package/UI/Components/Charts/Utils/XAxis.ts +75 -0
  391. package/UI/Components/Charts/Utils/useHistogramRangeSelection.ts +493 -59
  392. package/UI/Components/EntityDropdown/EntityDropdown.tsx +107 -11
  393. package/UI/Components/Forms/Fields/FormField.tsx +10 -0
  394. package/UI/Components/Input/Input.tsx +90 -57
  395. package/UI/Components/List/ListRow.tsx +8 -74
  396. package/UI/Components/LogsViewer/LogsViewer.tsx +40 -11
  397. package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +22 -6
  398. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +209 -6
  399. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +127 -84
  400. package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +3 -0
  401. package/UI/Components/ModelTable/BaseModelTable.tsx +12 -1
  402. package/UI/Components/MoreMenu/MoreMenu.tsx +365 -30
  403. package/UI/Components/MoreMenu/MoreMenuItem.tsx +70 -17
  404. package/UI/Components/OrderedStatesList/Item.tsx +7 -72
  405. package/UI/Components/StatusPage/ResourceGrid.tsx +126 -77
  406. package/UI/Components/Table/TableBody.tsx +8 -2
  407. package/UI/Components/Table/TableRow.tsx +20 -140
  408. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +41 -10
  409. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +47 -9
  410. package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +25 -6
  411. package/UI/Components/TelemetryViewer/types.ts +2 -0
  412. package/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.ts +448 -0
  413. package/UI/Components/Toggle/Toggle.tsx +26 -0
  414. package/UI/Components/Tooltip/Tooltip.tsx +8 -1
  415. package/UI/Styles/Theme.css +14 -2
  416. package/Utils/AiRemediation/CommandPolicy.ts +1 -1
  417. package/Utils/AiRemediation/KubectlPolicy.ts +1 -1
  418. package/Utils/Dashboard/DashboardTimeRangeZoom.ts +46 -2
  419. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  420. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  421. package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js +385 -0
  422. package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js.map +1 -0
  423. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +3 -3
  424. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  425. package/build/dist/Models/DatabaseModels/Project.js +56 -5
  426. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  427. package/build/dist/Models/DatabaseModels/ProxmoxResource.js +51 -1
  428. package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -1
  429. package/build/dist/Models/DatabaseModels/RunnerJob.js +74 -0
  430. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
  431. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +134 -3
  432. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
  433. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  434. package/build/dist/Server/API/AIChatAPI.js +6 -1
  435. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  436. package/build/dist/Server/API/AIInvestigationAPI.js +17 -10
  437. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  438. package/build/dist/Server/API/AutoRemediationAPI.js +144 -24
  439. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  440. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js +436 -22
  441. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js.map +1 -1
  442. package/build/dist/Server/API/MicrosoftTeamsAPI.js +69 -13
  443. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  444. package/build/dist/Server/API/ProxmoxResourceAPI.js +187 -14
  445. package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -1
  446. package/build/dist/Server/Infrastructure/GlobalCache.js +27 -0
  447. package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
  448. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js +50 -0
  449. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js.map +1 -0
  450. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js +84 -0
  451. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js.map +1 -0
  452. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js +31 -0
  453. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js.map +1 -0
  454. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  455. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  456. package/build/dist/Server/Middleware/TelemetryIngest.js +34 -19
  457. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  458. package/build/dist/Server/Services/AIService.js +59 -1
  459. package/build/dist/Server/Services/AIService.js.map +1 -1
  460. package/build/dist/Server/Services/AlertService.js +248 -13
  461. package/build/dist/Server/Services/AlertService.js.map +1 -1
  462. package/build/dist/Server/Services/AlertSeverityService.js +51 -15
  463. package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
  464. package/build/dist/Server/Services/AutoRemediationRuleService.js +1 -1
  465. package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -1
  466. package/build/dist/Server/Services/IncidentService.js +199 -72
  467. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  468. package/build/dist/Server/Services/IncidentSeverityService.js +51 -15
  469. package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
  470. package/build/dist/Server/Services/KubernetesAiAgentJobService.js +158 -0
  471. package/build/dist/Server/Services/KubernetesAiAgentJobService.js.map +1 -0
  472. package/build/dist/Server/Services/KubernetesAiAgentService.js +1145 -0
  473. package/build/dist/Server/Services/KubernetesAiAgentService.js.map +1 -0
  474. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js +842 -371
  475. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js.map +1 -1
  476. package/build/dist/Server/Services/KubernetesClusterService.js +86 -17
  477. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  478. package/build/dist/Server/Services/ProjectService.js +22 -0
  479. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  480. package/build/dist/Server/Services/ProxmoxResourceService.js +258 -3
  481. package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -1
  482. package/build/dist/Server/Services/RunnerJobService.js +178 -92
  483. package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
  484. package/build/dist/Server/Services/RunnerService.js +1 -1
  485. package/build/dist/Server/Services/RunnerService.js.map +1 -1
  486. package/build/dist/Server/Services/ScheduledMaintenanceService.js +535 -3
  487. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  488. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +316 -46
  489. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  490. package/build/dist/Server/Services/TeamComplianceSettingService.js +833 -7
  491. package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
  492. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js +52 -9
  493. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js.map +1 -1
  494. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +13 -9
  495. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
  496. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +7 -3
  497. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
  498. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +29 -15
  499. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  500. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +56 -20
  501. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  502. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +39 -5
  503. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  504. package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js +30 -3
  505. package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js.map +1 -1
  506. package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js +13 -2
  507. package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js.map +1 -1
  508. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +1 -1
  509. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +4 -2
  510. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
  511. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +111 -6
  512. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
  513. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +40 -4
  514. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -1
  515. package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js +296 -0
  516. package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js.map +1 -0
  517. package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js +699 -0
  518. package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js.map +1 -0
  519. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +77 -19
  520. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  521. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +505 -42
  522. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  523. package/build/dist/Types/AI/AIRunType.js +9 -4
  524. package/build/dist/Types/AI/AIRunType.js.map +1 -1
  525. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +10 -16
  526. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
  527. package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js +28 -0
  528. package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js.map +1 -0
  529. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +72 -16
  530. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
  531. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js +20 -16
  532. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js.map +1 -1
  533. package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js +17 -0
  534. package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js.map +1 -0
  535. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +4 -4
  536. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
  537. package/build/dist/Types/Team/ComplianceNotificationChannel.js +23 -0
  538. package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -0
  539. package/build/dist/Types/Team/ComplianceRule.js +304 -0
  540. package/build/dist/Types/Team/ComplianceRule.js.map +1 -0
  541. package/build/dist/Types/Team/ComplianceRuleType.js +21 -0
  542. package/build/dist/Types/Team/ComplianceRuleType.js.map +1 -1
  543. package/build/dist/Types/Team/TeamComplianceStatus.js +2 -0
  544. package/build/dist/Types/Team/TeamComplianceStatus.js.map +1 -0
  545. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +25 -0
  546. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
  547. package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js +20 -1
  548. package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js.map +1 -1
  549. package/build/dist/UI/Components/ActionButton/RowActions.js +113 -0
  550. package/build/dist/UI/Components/ActionButton/RowActions.js.map +1 -0
  551. package/build/dist/UI/Components/ActionButton/SplitActionButtons.js +71 -0
  552. package/build/dist/UI/Components/ActionButton/SplitActionButtons.js.map +1 -0
  553. package/build/dist/UI/Components/Charts/Area/AreaChart.js +16 -1
  554. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
  555. package/build/dist/UI/Components/Charts/Bar/BarChart.js +16 -1
  556. package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
  557. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +27 -5
  558. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  559. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +61 -194
  560. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  561. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +84 -26
  562. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  563. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +75 -196
  564. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  565. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +133 -0
  566. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -1
  567. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js +26 -0
  568. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js.map +1 -0
  569. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js +371 -0
  570. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js.map +1 -0
  571. package/build/dist/UI/Components/Charts/Line/LineChart.js +16 -1
  572. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  573. package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js +35 -0
  574. package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js.map +1 -0
  575. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js +107 -0
  576. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js.map +1 -0
  577. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js +41 -0
  578. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js.map +1 -0
  579. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js +117 -0
  580. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js.map +1 -0
  581. package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js +121 -0
  582. package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js.map +1 -0
  583. package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -7
  584. package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
  585. package/build/dist/UI/Components/Charts/Utils/XAxis.js +70 -0
  586. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  587. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js +305 -38
  588. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js.map +1 -1
  589. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +89 -14
  590. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  591. package/build/dist/UI/Components/Forms/Fields/FormField.js +11 -2
  592. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  593. package/build/dist/UI/Components/Input/Input.js +69 -54
  594. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  595. package/build/dist/UI/Components/List/ListRow.js +4 -39
  596. package/build/dist/UI/Components/List/ListRow.js.map +1 -1
  597. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +31 -8
  598. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  599. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +10 -1
  600. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
  601. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +139 -21
  602. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  603. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +30 -8
  604. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  605. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +1 -1
  606. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
  607. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +10 -0
  608. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  609. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +253 -14
  610. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  611. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +43 -13
  612. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
  613. package/build/dist/UI/Components/OrderedStatesList/Item.js +2 -38
  614. package/build/dist/UI/Components/OrderedStatesList/Item.js.map +1 -1
  615. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +53 -15
  616. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
  617. package/build/dist/UI/Components/Table/TableBody.js +6 -2
  618. package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
  619. package/build/dist/UI/Components/Table/TableRow.js +12 -75
  620. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  621. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +32 -7
  622. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  623. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +27 -9
  624. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  625. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +11 -1
  626. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
  627. package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js +272 -0
  628. package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js.map +1 -0
  629. package/build/dist/UI/Components/Toggle/Toggle.js +14 -1
  630. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  631. package/build/dist/UI/Components/Tooltip/Tooltip.js +1 -1
  632. package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
  633. package/build/dist/Utils/AiRemediation/CommandPolicy.js +1 -1
  634. package/build/dist/Utils/AiRemediation/CommandPolicy.js.map +1 -1
  635. package/build/dist/Utils/AiRemediation/KubectlPolicy.js +1 -1
  636. package/build/dist/Utils/AiRemediation/KubectlPolicy.js.map +1 -1
  637. package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +27 -1
  638. package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -1
  639. package/package.json +1 -1
@@ -0,0 +1,1057 @@
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
+ act,
12
+ cleanup,
13
+ fireEvent,
14
+ render,
15
+ RenderResult,
16
+ screen,
17
+ waitFor,
18
+ within,
19
+ } from "@testing-library/react";
20
+ import React, { ReactElement, ReactNode } from "react";
21
+ import getJestMockFunction, { MockFunction } from "../../MockType";
22
+
23
+ /*
24
+ * Issue #4105 on the incident and alert overview pages: a drag on the
25
+ * telemetry snapshot's metric chart zooms the WHOLE snapshot, so the slice
26
+ * is what the snapshot's Logs, Traces and Exceptions tabs show too. The
27
+ * page holds the zoom, above the tabs:
28
+ *
29
+ * - it survives a switch to another tab and back (the tabs mount only the
30
+ * open one, so a zoom kept in the chart was gone on the way back);
31
+ * - "Reset zoom" beside the snapshot badge, on any tab, and a double-click
32
+ * on the chart return every tab to the snapshot window;
33
+ * - the page's background refresh re-reads an equal snapshot and keeps it;
34
+ * a refresh that brings back a different window ends it;
35
+ * - the page stays mounted when the reader moves to another event, and one
36
+ * evaluation of a grouped monitor opens several events over the same
37
+ * window: the next event starts unzoomed, and so does coming back.
38
+ *
39
+ * A Logs snapshot's companion Metrics tab keeps a zoom of its own, and
40
+ * must keep it, and its way back, across the same refresh.
41
+ *
42
+ * The pages are rendered for real with every heavy card stubbed (the same
43
+ * stubs as EventOverviewTelemetrySnapshotZoom.test), and so is the snapshot
44
+ * card with its tabs. The metric charts (the snapshot's own, and the
45
+ * companion card's) are the real MetricView with MetricCharts stood in for
46
+ * by buttons that call exactly the handlers MetricView hands the charts;
47
+ * the logs, traces and exceptions explorers are stubs that record the query
48
+ * each tab hands them.
49
+ */
50
+
51
+ const getListMock: MockFunction = getJestMockFunction();
52
+ const getItemMock: MockFunction = getJestMockFunction();
53
+ const fetchResultsMock: MockFunction = getJestMockFunction();
54
+ const analyticsGetListMock: MockFunction = getJestMockFunction();
55
+
56
+ const recordedProps: Record<string, Array<Record<string, unknown>>> = {};
57
+
58
+ function recordProps(key: string, props: Record<string, unknown>): void {
59
+ if (!recordedProps[key]) {
60
+ recordedProps[key] = [];
61
+ }
62
+ recordedProps[key]!.push(props);
63
+ }
64
+
65
+ function stubModule(key: string): {
66
+ __esModule: boolean;
67
+ default: (props: Record<string, unknown>) => ReactElement;
68
+ } {
69
+ return {
70
+ __esModule: true,
71
+ default: (props: Record<string, unknown>): ReactElement => {
72
+ recordProps(key, props);
73
+ return React.createElement("div", { "data-testid": `stub-${key}` });
74
+ },
75
+ };
76
+ }
77
+
78
+ interface MockChartsProps {
79
+ onTimeRangeSelect?: ((startTime: Date, endTime: Date) => void) | undefined;
80
+ onTimeRangeReset?: (() => void) | undefined;
81
+ }
82
+
83
+ let mockLatestCharts: MockChartsProps | null = null;
84
+
85
+ const MOCK_DRAG: { start: Date; end: Date } = {
86
+ start: new Date("2026-09-14T17:52:00.000Z"),
87
+ end: new Date("2026-09-14T17:56:00.000Z"),
88
+ };
89
+
90
+ jest.mock(
91
+ "../../../../App/FeatureSet/Dashboard/src/Components/Metrics/MetricCharts",
92
+ () => {
93
+ return {
94
+ __esModule: true,
95
+ default: (props: MockChartsProps): ReactElement => {
96
+ mockLatestCharts = props;
97
+ return (
98
+ <div data-testid="metric-charts">
99
+ <button
100
+ type="button"
101
+ onClick={() => {
102
+ props.onTimeRangeSelect?.(MOCK_DRAG.start, MOCK_DRAG.end);
103
+ }}
104
+ >
105
+ Drag across the snapshot chart
106
+ </button>
107
+ <button
108
+ type="button"
109
+ onClick={() => {
110
+ props.onTimeRangeReset?.();
111
+ }}
112
+ >
113
+ Double-click the snapshot chart
114
+ </button>
115
+ </div>
116
+ );
117
+ },
118
+ };
119
+ },
120
+ );
121
+
122
+ jest.mock(
123
+ "../../../../App/FeatureSet/Dashboard/src/Components/Metrics/Utils/Metrics",
124
+ () => {
125
+ return {
126
+ __esModule: true,
127
+ default: {
128
+ fetchResults: (...args: Array<unknown>) => {
129
+ return fetchResultsMock(...args);
130
+ },
131
+ loadAllMetricsTypes: () => {
132
+ return Promise.resolve({ metricTypes: [], telemetryServices: [] });
133
+ },
134
+ getMetricTypes: () => {
135
+ return Promise.resolve([]);
136
+ },
137
+ clearQueryTopNOverridesForScope: () => {
138
+ return undefined;
139
+ },
140
+ },
141
+ };
142
+ },
143
+ );
144
+
145
+ jest.mock(
146
+ "../../../../App/FeatureSet/Dashboard/src/Components/Telemetry/useServiceNames",
147
+ () => {
148
+ return {
149
+ __esModule: true,
150
+ default: () => {
151
+ return {};
152
+ },
153
+ };
154
+ },
155
+ );
156
+
157
+ jest.mock(
158
+ "../../../../App/FeatureSet/Dashboard/src/Components/Metrics/Utils/UseEventTimeReferenceLines",
159
+ () => {
160
+ return {
161
+ __esModule: true,
162
+ default: () => {
163
+ return { lines: [], markerCount: 0 };
164
+ },
165
+ };
166
+ },
167
+ );
168
+
169
+ // The companion metric card's picker: shows the card's range.
170
+ jest.mock("../../../UI/Components/Date/RangeStartAndEndDateView", () => {
171
+ return {
172
+ __esModule: true,
173
+ default: (props: {
174
+ dashboardStartAndEndDate: {
175
+ range: string;
176
+ startAndEndDate?: { startValue: Date; endValue: Date };
177
+ };
178
+ }): ReactElement => {
179
+ const window: { startValue: Date; endValue: Date } | undefined =
180
+ props.dashboardStartAndEndDate.startAndEndDate;
181
+ return (
182
+ <span data-testid="card-picker">
183
+ {window
184
+ ? `${props.dashboardStartAndEndDate.range} ${window.startValue.toISOString()}..${window.endValue.toISOString()}`
185
+ : props.dashboardStartAndEndDate.range}
186
+ </span>
187
+ );
188
+ },
189
+ };
190
+ });
191
+
192
+ // The companion metric card looks up which metrics the scope has.
193
+ jest.mock("../../../UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI", () => {
194
+ return {
195
+ __esModule: true,
196
+ default: {
197
+ getList: (...args: Array<unknown>) => {
198
+ return analyticsGetListMock(...args);
199
+ },
200
+ },
201
+ };
202
+ });
203
+
204
+ jest.mock("react-i18next", () => {
205
+ return {
206
+ useTranslation: () => {
207
+ return {
208
+ t: (key: string, options?: { defaultValue?: string }): string => {
209
+ return options?.defaultValue ?? key;
210
+ },
211
+ };
212
+ },
213
+ };
214
+ });
215
+
216
+ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
217
+ return {
218
+ __esModule: true,
219
+ default: {
220
+ getList: (...args: Array<unknown>) => {
221
+ return getListMock(...args);
222
+ },
223
+ getItem: (...args: Array<unknown>) => {
224
+ return getItemMock(...args);
225
+ },
226
+ updateById: () => {
227
+ return Promise.resolve(undefined);
228
+ },
229
+ createOrUpdate: () => {
230
+ return Promise.resolve(undefined);
231
+ },
232
+ },
233
+ };
234
+ });
235
+
236
+ jest.mock("../../../UI/Components/ModelDetail/CardModelDetail", () => {
237
+ return {
238
+ __esModule: true,
239
+ default: (props: Record<string, unknown>): ReactElement => {
240
+ return React.createElement("div", {
241
+ "data-testid": `stub-card-${props["name"] as string}`,
242
+ });
243
+ },
244
+ };
245
+ });
246
+
247
+ jest.mock(
248
+ "../../../../App/FeatureSet/Dashboard/src/Components/AppLink/AppLink",
249
+ () => {
250
+ return {
251
+ __esModule: true,
252
+ default: (props: {
253
+ to?: { toString: () => string };
254
+ children: ReactNode;
255
+ }): ReactElement => {
256
+ return React.createElement(
257
+ "a",
258
+ { href: props.to?.toString() },
259
+ props.children,
260
+ );
261
+ },
262
+ };
263
+ },
264
+ );
265
+
266
+ jest.mock(
267
+ "../../../../App/FeatureSet/Dashboard/src/Components/Incident/ChangeState",
268
+ () => {
269
+ return stubModule("ChangeIncidentState");
270
+ },
271
+ );
272
+ jest.mock(
273
+ "../../../../App/FeatureSet/Dashboard/src/Components/Alert/ChangeState",
274
+ () => {
275
+ return stubModule("ChangeAlertState");
276
+ },
277
+ );
278
+ jest.mock(
279
+ "../../../../App/FeatureSet/Dashboard/src/Components/AI/InvestigationPanel",
280
+ () => {
281
+ return stubModule("InvestigationPanel");
282
+ },
283
+ );
284
+ jest.mock(
285
+ "../../../../App/FeatureSet/Dashboard/src/Components/Incident/IncidentFeed",
286
+ () => {
287
+ return stubModule("Feed");
288
+ },
289
+ );
290
+ jest.mock(
291
+ "../../../../App/FeatureSet/Dashboard/src/Components/Alert/AlertFeed",
292
+ () => {
293
+ return stubModule("Feed");
294
+ },
295
+ );
296
+ jest.mock(
297
+ "../../../../App/FeatureSet/Dashboard/src/Pages/Incidents/View/AffectedResources",
298
+ () => {
299
+ return stubModule("SeriesResource");
300
+ },
301
+ );
302
+ jest.mock(
303
+ "../../../../App/FeatureSet/Dashboard/src/Pages/Alerts/View/AffectedResources",
304
+ () => {
305
+ return stubModule("SeriesResource");
306
+ },
307
+ );
308
+ jest.mock(
309
+ "../../../../App/FeatureSet/Dashboard/src/Components/Monitor/MonitorSummarySnapshotCard",
310
+ () => {
311
+ return stubModule("MonitorSummary");
312
+ },
313
+ );
314
+ jest.mock(
315
+ "../../../../App/FeatureSet/Dashboard/src/Components/Runbook/EntityRunbooks",
316
+ () => {
317
+ return stubModule("Runbooks");
318
+ },
319
+ );
320
+ jest.mock(
321
+ "../../../../App/FeatureSet/Dashboard/src/Components/AutoRemediation/RemediationSuggestionCard",
322
+ () => {
323
+ return stubModule("Remediation");
324
+ },
325
+ );
326
+ jest.mock(
327
+ "../../../../App/FeatureSet/Dashboard/src/Components/Incident/IncidentMemberRoleAssignment",
328
+ () => {
329
+ return stubModule("Roles");
330
+ },
331
+ );
332
+ jest.mock(
333
+ "../../../../App/FeatureSet/Dashboard/src/Components/CustomFields/OverviewCustomFields",
334
+ () => {
335
+ return stubModule("CustomFields");
336
+ },
337
+ );
338
+ // The snapshot's companion explorers: record the query each tab hands them.
339
+ jest.mock(
340
+ "../../../../App/FeatureSet/Dashboard/src/Components/Logs/LogsViewer",
341
+ () => {
342
+ return stubModule("LogsViewer");
343
+ },
344
+ );
345
+ jest.mock(
346
+ "../../../../App/FeatureSet/Dashboard/src/Components/Traces/TracesViewer",
347
+ () => {
348
+ return stubModule("TracesViewer");
349
+ },
350
+ );
351
+ jest.mock(
352
+ "../../../../App/FeatureSet/Dashboard/src/Components/Exceptions/ExceptionsViewer",
353
+ () => {
354
+ return stubModule("ExceptionsViewer");
355
+ },
356
+ );
357
+ jest.mock(
358
+ "../../../../App/FeatureSet/Dashboard/src/Components/AffectedResources/AffectedResourcesDisplay",
359
+ () => {
360
+ return stubModule("AffectedResourcesDisplay");
361
+ },
362
+ );
363
+ jest.mock(
364
+ "../../../../App/FeatureSet/Dashboard/src/Components/AffectedResources/AffectedResourcesPicker",
365
+ () => {
366
+ return {
367
+ ...stubModule("AffectedResourcesPicker"),
368
+ isAffectedResourcesPayload: (): boolean => {
369
+ return false;
370
+ },
371
+ };
372
+ },
373
+ );
374
+ jest.mock(
375
+ "../../../../App/FeatureSet/Dashboard/src/Components/StatusPageSubscribers/SubscriberNotificationStatus",
376
+ () => {
377
+ return stubModule("SubscriberNotificationStatus");
378
+ },
379
+ );
380
+ jest.mock(
381
+ "../../../../App/FeatureSet/Dashboard/src/Components/OnCallPolicy/OnCallPolicies",
382
+ () => {
383
+ return stubModule("OnCallPolicies");
384
+ },
385
+ );
386
+ jest.mock(
387
+ "../../../../App/FeatureSet/Dashboard/src/Components/User/User",
388
+ () => {
389
+ return stubModule("User");
390
+ },
391
+ );
392
+ jest.mock(
393
+ "../../../../App/FeatureSet/Dashboard/src/Components/Monitor/Monitor",
394
+ () => {
395
+ return stubModule("Monitor");
396
+ },
397
+ );
398
+ jest.mock(
399
+ "../../../../App/FeatureSet/Dashboard/src/Components/AlertEpisode/AlertEpisode",
400
+ () => {
401
+ return stubModule("AlertEpisode");
402
+ },
403
+ );
404
+
405
+ import IncidentView from "../../../../App/FeatureSet/Dashboard/src/Pages/Incidents/View/Index";
406
+ import AlertView from "../../../../App/FeatureSet/Dashboard/src/Pages/Alerts/View/Index";
407
+ import PageComponentProps from "../../../../App/FeatureSet/Dashboard/src/Pages/PageComponentProps";
408
+ import { RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID } from "../../../UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton";
409
+ import Alert from "../../../Models/DatabaseModels/Alert";
410
+ import AlertState from "../../../Models/DatabaseModels/AlertState";
411
+ import AlertStateTimeline from "../../../Models/DatabaseModels/AlertStateTimeline";
412
+ import Incident from "../../../Models/DatabaseModels/Incident";
413
+ import IncidentState from "../../../Models/DatabaseModels/IncidentState";
414
+ import IncidentStateTimeline from "../../../Models/DatabaseModels/IncidentStateTimeline";
415
+ import Route from "../../../Types/API/Route";
416
+ import InBetween from "../../../Types/BaseDatabase/InBetween";
417
+ import OneUptimeDate from "../../../Types/Date";
418
+ import { JSONObject } from "../../../Types/JSON";
419
+ import JSONFunctions from "../../../Types/JSONFunctions";
420
+ import MetricViewData from "../../../Types/Metrics/MetricViewData";
421
+ import ObjectID from "../../../Types/ObjectID";
422
+ import Permission from "../../../Types/Permission";
423
+ import Navigation from "../../../UI/Utils/Navigation";
424
+ import PermissionUtil from "../../../UI/Utils/Permission";
425
+ import ProjectUtil from "../../../UI/Utils/Project";
426
+ import User from "../../../UI/Utils/User";
427
+
428
+ const EVENT_ID: string = "11111111-1111-4111-8111-111111111111";
429
+ // Opened by the same evaluation of a grouped monitor: the same window.
430
+ const SIBLING_EVENT_ID: string = "22222222-2222-4222-8222-222222222222";
431
+ const CREATED_STATE_ID: string = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaa1";
432
+
433
+ const NOW: Date = new Date("2026-09-14T19:00:00.000Z");
434
+ // The window the monitor evaluated over when it opened the event.
435
+ const SNAPSHOT_START: Date = new Date("2026-09-14T17:45:00.000Z");
436
+ const SNAPSHOT_END: Date = new Date("2026-09-14T18:00:00.000Z");
437
+ // A later evaluation's window, for a refresh that brings back another one.
438
+ const NEXT_START: Date = new Date("2026-09-14T18:30:00.000Z");
439
+ const NEXT_END: Date = new Date("2026-09-14T18:45:00.000Z");
440
+
441
+ const SNAPSHOT_TEXT: string = `${SNAPSHOT_START.toISOString()}..${SNAPSHOT_END.toISOString()}`;
442
+ const SLICE_TEXT: string = `${MOCK_DRAG.start.toISOString()}..${MOCK_DRAG.end.toISOString()}`;
443
+ const NEXT_TEXT: string = `${NEXT_START.toISOString()}..${NEXT_END.toISOString()}`;
444
+
445
+ const PAGE_PROPS: PageComponentProps = {
446
+ pageRoute: new Route("/overview"),
447
+ currentProject: null,
448
+ hasPaymentMethod: false,
449
+ };
450
+
451
+ // The window the snapshot's stored query is re-read with.
452
+ let mockStoredWindow: { start: Date; end: Date } = {
453
+ start: SNAPSHOT_START,
454
+ end: SNAPSHOT_END,
455
+ };
456
+ // What the monitor that opened the event evaluated.
457
+ let mockStoredType: "Metric" | "Log" = "Metric";
458
+ let mockEventId: string = EVENT_ID;
459
+
460
+ function textOf(window: { startValue: Date; endValue: Date }): string {
461
+ return `${OneUptimeDate.fromString(window.startValue).toISOString()}..${OneUptimeDate.fromString(window.endValue).toISOString()}`;
462
+ }
463
+
464
+ function fetchedChartWindows(): Array<string> {
465
+ return fetchResultsMock.mock.calls.map((call: Array<unknown>): string => {
466
+ const data: MetricViewData = (call[0] as { metricViewData: MetricViewData })
467
+ .metricViewData;
468
+ return textOf(data.startAndEndDate!);
469
+ });
470
+ }
471
+
472
+ function chartWindow(): string | undefined {
473
+ const windows: Array<string> = fetchedChartWindows();
474
+ return windows[windows.length - 1];
475
+ }
476
+
477
+ function charts(): MockChartsProps {
478
+ if (!mockLatestCharts) {
479
+ throw new Error("The snapshot chart has not rendered");
480
+ }
481
+ return mockLatestCharts;
482
+ }
483
+
484
+ function latestProps(key: string): Record<string, unknown> {
485
+ const calls: Array<Record<string, unknown>> = recordedProps[key] || [];
486
+ expect(calls.length).toBeGreaterThan(0);
487
+ return calls[calls.length - 1]!;
488
+ }
489
+
490
+ // The window a companion tab handed its explorer, by the query's own field.
491
+ function companionWindow(
492
+ key: string,
493
+ queryProp: string,
494
+ field: string,
495
+ ): string {
496
+ const query: Record<string, unknown> = latestProps(key)[queryProp] as Record<
497
+ string,
498
+ unknown
499
+ >;
500
+ return textOf(query[field] as InBetween<Date>);
501
+ }
502
+
503
+ function logsWindow(): string {
504
+ return companionWindow("LogsViewer", "logQuery", "time");
505
+ }
506
+
507
+ function tracesWindow(): string {
508
+ return companionWindow("TracesViewer", "spanQuery", "startTime");
509
+ }
510
+
511
+ function exceptionsWindow(): string {
512
+ return companionWindow("ExceptionsViewer", "exceptionInstanceQuery", "time");
513
+ }
514
+
515
+ function resetButtons(): Array<HTMLElement> {
516
+ return screen.queryAllByTestId(RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID);
517
+ }
518
+
519
+ /*
520
+ * The telemetryQuery exactly as the row stores it: serialized to JSON, so
521
+ * the window's bounds come back as ISO strings.
522
+ */
523
+ function storedMetricSnapshot(): JSONObject {
524
+ return {
525
+ telemetryType: "Metric",
526
+ telemetryQuery: null,
527
+ metricViewData: {
528
+ startAndEndDate: JSONFunctions.anyObjectToJSONObject(
529
+ new InBetween<Date>(mockStoredWindow.start, mockStoredWindow.end),
530
+ ),
531
+ queryConfigs: [
532
+ {
533
+ id: "query-1",
534
+ metricAliasData: {
535
+ metricVariable: "a",
536
+ title: "",
537
+ description: "",
538
+ legend: "",
539
+ legendUnit: "",
540
+ },
541
+ metricQueryData: {
542
+ filterData: {
543
+ metricName: "system.cpu.utilization",
544
+ aggegationType: "Avg",
545
+ },
546
+ },
547
+ },
548
+ ],
549
+ formulaConfigs: [],
550
+ },
551
+ };
552
+ }
553
+
554
+ // A log monitor's snapshot, stored the same way.
555
+ function storedLogSnapshot(): JSONObject {
556
+ return {
557
+ telemetryType: "Log",
558
+ telemetryQuery: {
559
+ time: JSONFunctions.anyObjectToJSONObject(
560
+ new InBetween<Date>(mockStoredWindow.start, mockStoredWindow.end),
561
+ ),
562
+ },
563
+ metricViewData: null,
564
+ };
565
+ }
566
+
567
+ function storedSnapshot(): JSONObject {
568
+ return mockStoredType === "Log"
569
+ ? storedLogSnapshot()
570
+ : storedMetricSnapshot();
571
+ }
572
+
573
+ interface PageCase {
574
+ renderPage: () => RenderResult;
575
+ page: () => ReactElement;
576
+ stateModel: typeof IncidentState | typeof AlertState;
577
+ timelineModel: typeof IncidentStateTimeline | typeof AlertStateTimeline;
578
+ changeStateKey: string;
579
+ buildEvent: () => Incident | Alert;
580
+ buildStates: () => Array<IncidentState | AlertState>;
581
+ buildTimeline: () => Array<IncidentStateTimeline | AlertStateTimeline>;
582
+ }
583
+
584
+ const INCIDENT_CASE: PageCase = {
585
+ page: (): ReactElement => {
586
+ return <IncidentView {...PAGE_PROPS} />;
587
+ },
588
+ renderPage: (): RenderResult => {
589
+ return render(<IncidentView {...PAGE_PROPS} />);
590
+ },
591
+ stateModel: IncidentState,
592
+ timelineModel: IncidentStateTimeline,
593
+ changeStateKey: "ChangeIncidentState",
594
+ buildEvent: (): Incident => {
595
+ const incident: Incident = new Incident();
596
+ incident.id = new ObjectID(mockEventId);
597
+ incident.title = "Checkout CPU saturated";
598
+ incident.incidentNumber = 42;
599
+ incident.declaredAt = SNAPSHOT_END;
600
+ incident.telemetryQuery = storedSnapshot() as never;
601
+ return incident;
602
+ },
603
+ buildStates: (): Array<IncidentState> => {
604
+ const state: IncidentState = new IncidentState();
605
+ state.id = new ObjectID(CREATED_STATE_ID);
606
+ state.name = "Created";
607
+ state.isCreatedState = true;
608
+ return [state];
609
+ },
610
+ buildTimeline: (): Array<IncidentStateTimeline> => {
611
+ const timeline: IncidentStateTimeline = new IncidentStateTimeline();
612
+ timeline.incidentStateId = new ObjectID(CREATED_STATE_ID);
613
+ timeline.startsAt = SNAPSHOT_END;
614
+ return [timeline];
615
+ },
616
+ };
617
+
618
+ const ALERT_CASE: PageCase = {
619
+ page: (): ReactElement => {
620
+ return <AlertView {...PAGE_PROPS} />;
621
+ },
622
+ renderPage: (): RenderResult => {
623
+ return render(<AlertView {...PAGE_PROPS} />);
624
+ },
625
+ stateModel: AlertState,
626
+ timelineModel: AlertStateTimeline,
627
+ changeStateKey: "ChangeAlertState",
628
+ buildEvent: (): Alert => {
629
+ const alert: Alert = new Alert();
630
+ alert.id = new ObjectID(mockEventId);
631
+ alert.title = "Checkout CPU saturated";
632
+ alert.alertNumber = 12;
633
+ alert.createdAt = SNAPSHOT_END;
634
+ alert.telemetryQuery = storedSnapshot() as never;
635
+ return alert;
636
+ },
637
+ buildStates: (): Array<AlertState> => {
638
+ const state: AlertState = new AlertState();
639
+ state.id = new ObjectID(CREATED_STATE_ID);
640
+ state.name = "Created";
641
+ state.isCreatedState = true;
642
+ return [state];
643
+ },
644
+ buildTimeline: (): Array<AlertStateTimeline> => {
645
+ const timeline: AlertStateTimeline = new AlertStateTimeline();
646
+ timeline.alertStateId = new ObjectID(CREATED_STATE_ID);
647
+ timeline.startsAt = SNAPSHOT_END;
648
+ return [timeline];
649
+ },
650
+ };
651
+
652
+ function serve(pageCase: PageCase): void {
653
+ getListMock.mockImplementation((...args: Array<unknown>) => {
654
+ const request: { modelType: unknown } = args[0] as { modelType: unknown };
655
+ const data: Array<unknown> =
656
+ request.modelType === pageCase.stateModel
657
+ ? pageCase.buildStates()
658
+ : request.modelType === pageCase.timelineModel
659
+ ? pageCase.buildTimeline()
660
+ : [];
661
+ return Promise.resolve({
662
+ data: data,
663
+ count: data.length,
664
+ skip: 0,
665
+ limit: 10000,
666
+ });
667
+ });
668
+ getItemMock.mockImplementation(() => {
669
+ return Promise.resolve(pageCase.buildEvent());
670
+ });
671
+ }
672
+
673
+ /*
674
+ * MetricView draws its charts once before it loads, then shows a loader
675
+ * until its first fetch lands: wait for that fetch and the charts after.
676
+ */
677
+ async function chartSettled(): Promise<void> {
678
+ await waitFor(() => {
679
+ expect(fetchedChartWindows().length).toBeGreaterThan(0);
680
+ expect(screen.getByTestId("metric-charts")).toBeInTheDocument();
681
+ });
682
+ }
683
+
684
+ async function renderSettled(pageCase: PageCase): Promise<RenderResult> {
685
+ serve(pageCase);
686
+ const rendered: RenderResult = pageCase.renderPage();
687
+ await chartSettled();
688
+ return rendered;
689
+ }
690
+
691
+ async function press(label: string): Promise<void> {
692
+ fireEvent.click(await screen.findByRole("button", { name: label }));
693
+ }
694
+
695
+ async function openTab(name: string): Promise<void> {
696
+ // Found outside act: the page may still be loading its first read.
697
+ const tab: HTMLElement = await screen.findByRole("tab", { name: name });
698
+ await act(async () => {
699
+ fireEvent.click(tab);
700
+ });
701
+ }
702
+
703
+ async function zoomTheSnapshot(): Promise<void> {
704
+ await press("Drag across the snapshot chart");
705
+ await waitFor(() => {
706
+ expect(chartWindow()).toBe(SLICE_TEXT);
707
+ });
708
+ }
709
+
710
+ async function backOnMetrics(): Promise<void> {
711
+ await openTab("Metrics");
712
+ await chartSettled();
713
+ }
714
+
715
+ // A state change on the page: it re-reads the event in the background.
716
+ async function refreshThePage(pageCase: PageCase): Promise<void> {
717
+ const reads: number = getItemMock.mock.calls.length;
718
+ const changeState: { onActionComplete: () => void } = latestProps(
719
+ pageCase.changeStateKey,
720
+ ) as unknown as { onActionComplete: () => void };
721
+ await act(async () => {
722
+ changeState.onActionComplete();
723
+ });
724
+ await waitFor(() => {
725
+ expect(getItemMock.mock.calls.length).toBeGreaterThan(reads);
726
+ });
727
+ }
728
+
729
+ function badgeTitle(): string {
730
+ return OneUptimeDate.getInBetweenDatesAsFormattedString(
731
+ new InBetween<Date>(SNAPSHOT_START, SNAPSHOT_END),
732
+ );
733
+ }
734
+
735
+ beforeEach(() => {
736
+ jest.useFakeTimers({ doNotFake: ["nextTick", "setImmediate"] });
737
+ jest.setSystemTime(NOW);
738
+ mockLatestCharts = null;
739
+ mockStoredWindow = { start: SNAPSHOT_START, end: SNAPSHOT_END };
740
+ mockStoredType = "Metric";
741
+ mockEventId = EVENT_ID;
742
+ fetchResultsMock.mockReset();
743
+ fetchResultsMock.mockImplementation(() => {
744
+ return Promise.resolve([{ data: [], truncated: false }]);
745
+ });
746
+ analyticsGetListMock.mockReset();
747
+ analyticsGetListMock.mockResolvedValue({
748
+ data: [{ name: "checkout.latency" }],
749
+ });
750
+ jest.spyOn(Navigation, "getLastParamAsObjectID").mockImplementation(() => {
751
+ return new ObjectID(mockEventId);
752
+ });
753
+ jest.spyOn(PermissionUtil, "getAllPermissions").mockImplementation(() => {
754
+ return [Permission.ProjectMember];
755
+ });
756
+ jest.spyOn(User, "isMasterAdmin").mockReturnValue(false);
757
+ });
758
+
759
+ afterEach(() => {
760
+ cleanup();
761
+ getListMock.mockReset();
762
+ getItemMock.mockReset();
763
+ for (const key of Object.keys(recordedProps)) {
764
+ delete recordedProps[key];
765
+ }
766
+ jest.restoreAllMocks();
767
+ jest.useRealTimers();
768
+ });
769
+
770
+ describe.each([
771
+ ["incident", INCIDENT_CASE],
772
+ ["alert", ALERT_CASE],
773
+ ])(
774
+ "the %s overview's snapshot zooms as one",
775
+ (_name: string, pageCase: PageCase) => {
776
+ test("before any drag, the companion tabs are on the snapshot window", async () => {
777
+ await renderSettled(pageCase);
778
+
779
+ expect(chartWindow()).toBe(SNAPSHOT_TEXT);
780
+ await openTab("Logs");
781
+ expect(logsWindow()).toBe(SNAPSHOT_TEXT);
782
+ });
783
+
784
+ test("a drag on the chart hands the slice to the Logs, Traces and Exceptions tabs", async () => {
785
+ await renderSettled(pageCase);
786
+ const pageReads: number = getItemMock.mock.calls.length;
787
+
788
+ await zoomTheSnapshot();
789
+
790
+ await openTab("Logs");
791
+ expect(logsWindow()).toBe(SLICE_TEXT);
792
+ await openTab("Traces");
793
+ expect(tracesWindow()).toBe(SLICE_TEXT);
794
+ await openTab("Exceptions");
795
+ expect(exceptionsWindow()).toBe(SLICE_TEXT);
796
+ // A zoom is not a reload of the page.
797
+ expect(getItemMock.mock.calls.length).toBe(pageReads);
798
+ });
799
+
800
+ test("the companion explorers' empty states name the zoomed part of the snapshot window, until a reset", async () => {
801
+ await renderSettled(pageCase);
802
+ await zoomTheSnapshot();
803
+
804
+ await openTab("Logs");
805
+ expect(latestProps("LogsViewer")["noLogsMessage"]).toBe(
806
+ "No logs found in the zoomed part of the snapshot window.",
807
+ );
808
+ await openTab("Traces");
809
+ expect(latestProps("TracesViewer")["emptyMessage"]).toBe(
810
+ "No spans found in the zoomed part of the snapshot window.",
811
+ );
812
+ await openTab("Exceptions");
813
+ expect(latestProps("ExceptionsViewer")["emptyMessage"]).toBe(
814
+ "No exceptions found in the zoomed part of the snapshot window.",
815
+ );
816
+
817
+ await act(async () => {
818
+ fireEvent.click(
819
+ screen.getByTestId(RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID),
820
+ );
821
+ });
822
+ expect(latestProps("ExceptionsViewer")["emptyMessage"]).toBe(
823
+ "No exceptions found in the snapshot window.",
824
+ );
825
+ await openTab("Logs");
826
+ expect(latestProps("LogsViewer")["noLogsMessage"]).toBe(
827
+ "No logs found in the snapshot window.",
828
+ );
829
+ });
830
+
831
+ test("back on the Metrics tab the chart is still on the slice, with its way back", async () => {
832
+ await renderSettled(pageCase);
833
+ await zoomTheSnapshot();
834
+ await openTab("Logs");
835
+
836
+ await backOnMetrics();
837
+
838
+ expect(chartWindow()).toBe(SLICE_TEXT);
839
+ expect(charts().onTimeRangeReset).toBeInstanceOf(Function);
840
+ expect(resetButtons()).toHaveLength(1);
841
+ });
842
+
843
+ test("every tab's card names the snapshot window and offers Reset zoom while zoomed", async () => {
844
+ await renderSettled(pageCase);
845
+ await zoomTheSnapshot();
846
+
847
+ for (const tabName of ["Metrics", "Logs", "Traces", "Exceptions"]) {
848
+ await openTab(tabName);
849
+ const tabPanel: HTMLElement = screen.getByRole("tabpanel");
850
+ expect(within(tabPanel).getByText(badgeTitle())).toBeInTheDocument();
851
+ expect(
852
+ within(tabPanel).getByTestId(RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID),
853
+ ).toBeVisible();
854
+ }
855
+ });
856
+
857
+ test("Reset zoom on the Logs tab returns every tab to the snapshot window", async () => {
858
+ await renderSettled(pageCase);
859
+ await zoomTheSnapshot();
860
+ await openTab("Logs");
861
+
862
+ await act(async () => {
863
+ fireEvent.click(
864
+ screen.getByTestId(RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID),
865
+ );
866
+ });
867
+
868
+ expect(logsWindow()).toBe(SNAPSHOT_TEXT);
869
+ expect(resetButtons()).toHaveLength(0);
870
+ await backOnMetrics();
871
+ expect(chartWindow()).toBe(SNAPSHOT_TEXT);
872
+ expect(charts().onTimeRangeReset).toBeUndefined();
873
+ await openTab("Traces");
874
+ expect(tracesWindow()).toBe(SNAPSHOT_TEXT);
875
+ });
876
+
877
+ test("a double-click on the chart after a round trip returns every tab to the snapshot window", async () => {
878
+ await renderSettled(pageCase);
879
+ await zoomTheSnapshot();
880
+ await openTab("Exceptions");
881
+ await backOnMetrics();
882
+ expect(charts().onTimeRangeReset).toBeInstanceOf(Function);
883
+
884
+ await press("Double-click the snapshot chart");
885
+
886
+ await waitFor(() => {
887
+ expect(chartWindow()).toBe(SNAPSHOT_TEXT);
888
+ });
889
+ expect(resetButtons()).toHaveLength(0);
890
+ await openTab("Exceptions");
891
+ expect(exceptionsWindow()).toBe(SNAPSHOT_TEXT);
892
+ });
893
+
894
+ test("the page's background refresh keeps the zoom on every tab", async () => {
895
+ await renderSettled(pageCase);
896
+ await zoomTheSnapshot();
897
+
898
+ await refreshThePage(pageCase);
899
+
900
+ expect(chartWindow()).toBe(SLICE_TEXT);
901
+ expect(charts().onTimeRangeReset).toBeInstanceOf(Function);
902
+ expect(resetButtons()).toHaveLength(1);
903
+ await openTab("Logs");
904
+ expect(logsWindow()).toBe(SLICE_TEXT);
905
+ });
906
+
907
+ test("a refresh with a tab open hands that tab the very same query", async () => {
908
+ await renderSettled(pageCase);
909
+ await zoomTheSnapshot();
910
+ await openTab("Logs");
911
+ const logQuery: unknown = latestProps("LogsViewer")["logQuery"];
912
+
913
+ await refreshThePage(pageCase);
914
+
915
+ // Not even a new-but-equal object: nothing for the explorer to redo.
916
+ expect(latestProps("LogsViewer")["logQuery"]).toBe(logQuery);
917
+ expect(logsWindow()).toBe(SLICE_TEXT);
918
+ });
919
+
920
+ test("a refresh that brings back a different window ends the zoom on every tab", async () => {
921
+ await renderSettled(pageCase);
922
+ await zoomTheSnapshot();
923
+
924
+ mockStoredWindow = { start: NEXT_START, end: NEXT_END };
925
+ await refreshThePage(pageCase);
926
+
927
+ await waitFor(() => {
928
+ expect(chartWindow()).toBe(NEXT_TEXT);
929
+ });
930
+ expect(charts().onTimeRangeReset).toBeUndefined();
931
+ expect(resetButtons()).toHaveLength(0);
932
+ await openTab("Logs");
933
+ expect(logsWindow()).toBe(NEXT_TEXT);
934
+ });
935
+
936
+ test("another event from the same evaluation (same window) starts unzoomed, and so does coming back", async () => {
937
+ const rendered: RenderResult = await renderSettled(pageCase);
938
+ await zoomTheSnapshot();
939
+
940
+ // The reader follows a link to the sibling event: same route, same page.
941
+ mockEventId = SIBLING_EVENT_ID;
942
+ fetchResultsMock.mockClear();
943
+ rendered.rerender(pageCase.page());
944
+ await chartSettled();
945
+
946
+ expect(chartWindow()).toBe(SNAPSHOT_TEXT);
947
+ expect(charts().onTimeRangeReset).toBeUndefined();
948
+ expect(resetButtons()).toHaveLength(0);
949
+ await openTab("Logs");
950
+ expect(logsWindow()).toBe(SNAPSHOT_TEXT);
951
+
952
+ // And back to the first one: its zoom stayed behind with it.
953
+ mockEventId = EVENT_ID;
954
+ fetchResultsMock.mockClear();
955
+ rendered.rerender(pageCase.page());
956
+ await chartSettled();
957
+
958
+ expect(chartWindow()).toBe(SNAPSHOT_TEXT);
959
+ expect(resetButtons()).toHaveLength(0);
960
+ });
961
+ },
962
+ );
963
+
964
+ /*
965
+ * A Logs snapshot: the Metrics tab is a companion, an embedded metric card
966
+ * that zooms on its own terms. The page's background refresh re-reads the
967
+ * snapshot after every acknowledge or edit; it used to reload that card and
968
+ * forget its zoom while the tab kept the zoomed window, leaving the chart on
969
+ * the slice with no Reset zoom and a double-click that did nothing.
970
+ */
971
+ describe.each([
972
+ ["incident", INCIDENT_CASE],
973
+ ["alert", ALERT_CASE],
974
+ ])(
975
+ "the %s overview's Logs snapshot: its companion Metrics tab across the page's refresh",
976
+ (_name: string, pageCase: PageCase) => {
977
+ beforeEach(() => {
978
+ mockStoredType = "Log";
979
+ jest
980
+ .spyOn(ProjectUtil, "getCurrentProjectId")
981
+ .mockReturnValue(new ObjectID("33333333-3333-4333-8333-333333333333"));
982
+ });
983
+
984
+ function cardPicker(): string {
985
+ return screen.getByTestId("card-picker").textContent || "";
986
+ }
987
+
988
+ async function openTheCompanionCard(): Promise<void> {
989
+ serve(pageCase);
990
+ pageCase.renderPage();
991
+ await openTab("Metrics");
992
+ await chartSettled();
993
+ expect(chartWindow()).toBe(SNAPSHOT_TEXT);
994
+ }
995
+
996
+ async function zoomTheCard(): Promise<void> {
997
+ await zoomTheSnapshot();
998
+ await waitFor(() => {
999
+ expect(charts().onTimeRangeReset).toBeInstanceOf(Function);
1000
+ });
1001
+ // The card's own way back: the snapshot itself is not zoomed.
1002
+ expect(resetButtons()).toHaveLength(1);
1003
+ }
1004
+
1005
+ test("the refresh keeps the card's zoom and its way back, without reloading the card", async () => {
1006
+ await openTheCompanionCard();
1007
+ await zoomTheCard();
1008
+ const lookups: number = analyticsGetListMock.mock.calls.length;
1009
+ const chartsBefore: HTMLElement = screen.getByTestId("metric-charts");
1010
+
1011
+ await refreshThePage(pageCase);
1012
+
1013
+ expect(chartWindow()).toBe(SLICE_TEXT);
1014
+ expect(cardPicker()).toBe(
1015
+ `Custom ${MOCK_DRAG.start.toISOString()}..${MOCK_DRAG.end.toISOString()}`,
1016
+ );
1017
+ expect(resetButtons()).toHaveLength(1);
1018
+ expect(charts().onTimeRangeReset).toBeInstanceOf(Function);
1019
+ // Never blanked behind a loader, never looked up again.
1020
+ expect(screen.getByTestId("metric-charts")).toBe(chartsBefore);
1021
+ expect(analyticsGetListMock.mock.calls.length).toBe(lookups);
1022
+ });
1023
+
1024
+ test("a double-click after the refresh returns the card to the snapshot window", async () => {
1025
+ await openTheCompanionCard();
1026
+ await zoomTheCard();
1027
+ await refreshThePage(pageCase);
1028
+
1029
+ await press("Double-click the snapshot chart");
1030
+
1031
+ await waitFor(() => {
1032
+ expect(chartWindow()).toBe(SNAPSHOT_TEXT);
1033
+ });
1034
+ expect(cardPicker()).toBe(
1035
+ `Custom ${SNAPSHOT_START.toISOString()}..${SNAPSHOT_END.toISOString()}`,
1036
+ );
1037
+ expect(resetButtons()).toHaveLength(0);
1038
+ });
1039
+
1040
+ test("Reset zoom after the refresh returns the card to the snapshot window", async () => {
1041
+ await openTheCompanionCard();
1042
+ await zoomTheCard();
1043
+ await refreshThePage(pageCase);
1044
+
1045
+ await act(async () => {
1046
+ fireEvent.click(
1047
+ screen.getByTestId(RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID),
1048
+ );
1049
+ });
1050
+
1051
+ await waitFor(() => {
1052
+ expect(chartWindow()).toBe(SNAPSHOT_TEXT);
1053
+ });
1054
+ expect(resetButtons()).toHaveLength(0);
1055
+ });
1056
+ },
1057
+ );