@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,952 @@
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
+ screen,
16
+ waitFor,
17
+ within,
18
+ } from "@testing-library/react";
19
+ import * as React from "react";
20
+ import { MemoryRouter } from "react-router-dom";
21
+ import getJestMockFunction, { MockFunction } from "../../MockType";
22
+
23
+ /*
24
+ * Where MetricView's own "Reset zoom" goes (issue #4105).
25
+ *
26
+ * Where the view keeps the zoom itself (localChartZoom, or its own window)
27
+ * it offers "Reset zoom" while zoomed. It used to add a row for it ABOVE
28
+ * the whole view, only while zoomed: every zoom pushed the charts (and, in
29
+ * the ten monitor step forms, the whole query builder) down by that row
30
+ * and every reset pulled them back up, right under a reader about to
31
+ * double-click; and in the step forms the button sat above the query
32
+ * editors, far from the chart it resets and often scrolled out of sight.
33
+ *
34
+ * Now showing it moves nothing, and it sits with the charts:
35
+ * - with the query builder shown, at the end of the "Charts" heading row
36
+ * that is always there;
37
+ * - without it, floating (absolutely placed) on the first chart's top
38
+ * border, together with the refetch indicator, which used to hold that
39
+ * corner by itself.
40
+ * Where the page or the host keeps the zoom, they offer the reset, and the
41
+ * view adds none.
42
+ *
43
+ * The forms and MetricView are real; MetricCharts is stood in for with
44
+ * buttons that call exactly the handlers MetricView hands the charts.
45
+ */
46
+
47
+ const getListMock: MockFunction = getJestMockFunction();
48
+ const getItemMock: MockFunction = getJestMockFunction();
49
+ const fetchResultsMock: MockFunction = getJestMockFunction();
50
+
51
+ interface MockChartsProps {
52
+ metricViewData: {
53
+ queryConfigs: Array<{
54
+ metricQueryData: { filterData: { metricName?: unknown } };
55
+ }>;
56
+ };
57
+ onTimeRangeSelect?: ((startTime: Date, endTime: Date) => void) | undefined;
58
+ onTimeRangeReset?: (() => void) | undefined;
59
+ }
60
+
61
+ const MOCK_DRAG: { start: Date; end: Date } = {
62
+ start: new Date("2026-09-28T11:20:00.000Z"),
63
+ end: new Date("2026-09-28T11:30:00.000Z"),
64
+ };
65
+
66
+ jest.mock(
67
+ "../../../../App/FeatureSet/Dashboard/src/Components/Metrics/MetricCharts",
68
+ () => {
69
+ return {
70
+ __esModule: true,
71
+ default: (props: MockChartsProps): React.ReactElement => {
72
+ return (
73
+ <div data-testid="metric-charts">
74
+ <button
75
+ type="button"
76
+ onClick={() => {
77
+ props.onTimeRangeSelect?.(MOCK_DRAG.start, MOCK_DRAG.end);
78
+ }}
79
+ >
80
+ Drag across the chart
81
+ </button>
82
+ <button
83
+ type="button"
84
+ onClick={() => {
85
+ props.onTimeRangeReset?.();
86
+ }}
87
+ >
88
+ Double-click the chart
89
+ </button>
90
+ </div>
91
+ );
92
+ },
93
+ };
94
+ },
95
+ );
96
+
97
+ jest.mock(
98
+ "../../../../App/FeatureSet/Dashboard/src/Components/Metrics/Utils/Metrics",
99
+ () => {
100
+ return {
101
+ __esModule: true,
102
+ default: {
103
+ fetchResults: (...args: Array<unknown>) => {
104
+ return fetchResultsMock(...args);
105
+ },
106
+ /*
107
+ * The metric catalog answers after the first results have landed
108
+ * (longer than one waitFor tick). Answered first, MetricView's
109
+ * mount-time load drops the Metric step form's first result: a
110
+ * fetch from the first render, before the form set its window,
111
+ * supersedes it. That is not what is pinned here.
112
+ */
113
+ loadAllMetricsTypes: () => {
114
+ return new Promise(
115
+ (
116
+ resolve: (value: {
117
+ metricTypes: Array<unknown>;
118
+ telemetryServices: Array<unknown>;
119
+ }) => void,
120
+ ) => {
121
+ setTimeout(() => {
122
+ resolve({ metricTypes: [], telemetryServices: [] });
123
+ }, 200);
124
+ },
125
+ );
126
+ },
127
+ getMetricTypes: () => {
128
+ return Promise.resolve([]);
129
+ },
130
+ clearQueryTopNOverridesForScope: () => {
131
+ return undefined;
132
+ },
133
+ },
134
+ };
135
+ },
136
+ );
137
+
138
+ // The forms' dropdowns (hosts, clusters, rolling time) as plain selects.
139
+ jest.mock("../../../UI/Components/Dropdown/Dropdown", () => {
140
+ return {
141
+ __esModule: true,
142
+ default: (props: {
143
+ options: Array<{ label: string; value: unknown }>;
144
+ value?: { value: unknown } | undefined;
145
+ onChange?: ((value: unknown) => void) | undefined;
146
+ }) => {
147
+ return (
148
+ <select
149
+ value={String(props.value?.value ?? "")}
150
+ onChange={(event: React.ChangeEvent<HTMLSelectElement>) => {
151
+ props.onChange?.(event.target.value);
152
+ }}
153
+ >
154
+ <option value="">Select</option>
155
+ {(props.options || []).map(
156
+ (option: { label: string; value: unknown }) => {
157
+ return (
158
+ <option key={String(option.value)} value={String(option.value)}>
159
+ {option.label}
160
+ </option>
161
+ );
162
+ },
163
+ )}
164
+ </select>
165
+ );
166
+ },
167
+ };
168
+ });
169
+
170
+ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
171
+ return {
172
+ __esModule: true,
173
+ default: {
174
+ getList: (...args: Array<unknown>) => {
175
+ return getListMock(...args);
176
+ },
177
+ getItem: (...args: Array<unknown>) => {
178
+ return getItemMock(...args);
179
+ },
180
+ },
181
+ };
182
+ });
183
+
184
+ jest.mock("../../../UI/Utils/Project", () => {
185
+ return {
186
+ __esModule: true,
187
+ default: {
188
+ getCurrentProjectId: () => {
189
+ return new ObjectID("99999999-9999-4999-8999-999999999999");
190
+ },
191
+ },
192
+ };
193
+ });
194
+
195
+ import MetricView from "../../../../App/FeatureSet/Dashboard/src/Components/Metrics/MetricView";
196
+ import MetricMonitorStepForm from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/MetricMonitor/MetricMonitorStepForm";
197
+ import HostMonitorStepForm from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/HostMonitor/HostMonitorStepForm";
198
+ import KubernetesMonitorStepForm from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/KubernetesMonitor/KubernetesMonitorStepForm";
199
+ import DockerMonitorStepForm from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/DockerMonitor/DockerMonitorStepForm";
200
+ import DockerSwarmMonitorStepForm from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/DockerSwarmMonitor/DockerSwarmMonitorStepForm";
201
+ import PodmanMonitorStepForm from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/PodmanMonitor/PodmanMonitorStepForm";
202
+ import ProxmoxMonitorStepForm from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/ProxmoxMonitor/ProxmoxMonitorStepForm";
203
+ import VMwareMonitorStepForm from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/VMwareMonitor/VMwareMonitorStepForm";
204
+ import CephMonitorStepForm from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/CephMonitor/CephMonitorStepForm";
205
+ import IoTMonitorStepForm from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/IoTMonitor/IoTMonitorStepForm";
206
+ import { TimeRangeZoomProvider } from "../../../UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext";
207
+ import { TimeRangeZoom } from "../../../UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom";
208
+ import { RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID } from "../../../UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton";
209
+ import InBetween from "../../../Types/BaseDatabase/InBetween";
210
+ import MetricsAggregationType from "../../../Types/Metrics/MetricsAggregationType";
211
+ import MetricsViewConfig from "../../../Types/Metrics/MetricsViewConfig";
212
+ import MetricViewData from "../../../Types/Metrics/MetricViewData";
213
+ import { MonitorStepMetricMonitorUtil } from "../../../Types/Monitor/MonitorStepMetricMonitor";
214
+ import { MonitorStepHostMonitorUtil } from "../../../Types/Monitor/MonitorStepHostMonitor";
215
+ import { MonitorStepKubernetesMonitorUtil } from "../../../Types/Monitor/MonitorStepKubernetesMonitor";
216
+ import { MonitorStepDockerMonitorUtil } from "../../../Types/Monitor/MonitorStepDockerMonitor";
217
+ import { MonitorStepDockerSwarmMonitorUtil } from "../../../Types/Monitor/MonitorStepDockerSwarmMonitor";
218
+ import { MonitorStepPodmanMonitorUtil } from "../../../Types/Monitor/MonitorStepPodmanMonitor";
219
+ import { MonitorStepProxmoxMonitorUtil } from "../../../Types/Monitor/MonitorStepProxmoxMonitor";
220
+ import { MonitorStepVMwareMonitorUtil } from "../../../Types/Monitor/MonitorStepVMwareMonitor";
221
+ import { MonitorStepCephMonitorUtil } from "../../../Types/Monitor/MonitorStepCephMonitor";
222
+ import { MonitorStepIoTMonitorUtil } from "../../../Types/Monitor/MonitorStepIoTMonitor";
223
+ import ObjectID from "../../../Types/ObjectID";
224
+ import RollingTime from "../../../Types/RollingTime/RollingTime";
225
+ import TimeRange from "../../../Types/Time/TimeRange";
226
+
227
+ const NOW: Date = new Date("2026-09-28T12:00:00.000Z");
228
+ const WINDOW_START: Date = new Date("2026-09-28T11:00:00.000Z");
229
+
230
+ // The test id of the floating pair: "Reset zoom" and the refetch indicator.
231
+ const OWN_ZOOM_CONTROLS_TEST_ID: string = "metric-view-own-zoom-controls";
232
+
233
+ function viewConfigFor(metricName: string): MetricsViewConfig {
234
+ return {
235
+ queryConfigs: [
236
+ {
237
+ metricAliasData: {
238
+ metricVariable: "a",
239
+ title: metricName,
240
+ description: "",
241
+ legend: "",
242
+ legendUnit: "",
243
+ },
244
+ metricQueryData: {
245
+ filterData: {
246
+ metricName: metricName,
247
+ aggegationType: MetricsAggregationType.Avg,
248
+ },
249
+ },
250
+ },
251
+ ],
252
+ formulaConfigs: [],
253
+ };
254
+ }
255
+
256
+ function viewDataFor(metricName: string): MetricViewData {
257
+ return {
258
+ ...viewConfigFor(metricName),
259
+ startAndEndDate: new InBetween<Date>(WINDOW_START, NOW),
260
+ } as MetricViewData;
261
+ }
262
+
263
+ function resetButton(): HTMLElement | null {
264
+ return screen.queryByTestId(RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID);
265
+ }
266
+
267
+ function chartsStandIn(): HTMLElement {
268
+ return screen.getByTestId("metric-charts");
269
+ }
270
+
271
+ // Whether `later` comes after `earlier` in document order.
272
+ function follows(later: Node, earlier: Node): boolean {
273
+ return Boolean(
274
+ earlier.compareDocumentPosition(later) & Node.DOCUMENT_POSITION_FOLLOWING,
275
+ );
276
+ }
277
+
278
+ /*
279
+ * The "Charts" heading row MetricView draws above its charts whenever the
280
+ * query builder is shown.
281
+ */
282
+ function chartsHeadingRow(): HTMLElement {
283
+ const label: HTMLElement | undefined = screen
284
+ .getAllByText("Charts")
285
+ .find((element: HTMLElement): boolean => {
286
+ return element.tagName === "SPAN";
287
+ });
288
+ if (!label || !label.parentElement) {
289
+ throw new Error('No "Charts" heading row');
290
+ }
291
+ return label.parentElement;
292
+ }
293
+
294
+ // Every element on the path from `root` down to `node`, in order.
295
+ function pathTo(root: HTMLElement, node: HTMLElement): Array<HTMLElement> {
296
+ const path: Array<HTMLElement> = [];
297
+ let current: HTMLElement | null = node;
298
+ while (current && current !== root) {
299
+ path.unshift(current);
300
+ current = current.parentElement;
301
+ }
302
+ return path;
303
+ }
304
+
305
+ /*
306
+ * The in-flow layout above the charts, as each element on the path from
307
+ * the host down to the charts and the siblings laid out before it: an
308
+ * element added to or dropped from the flow above the charts changes it.
309
+ * Absolutely placed elements are left out: they move nothing.
310
+ */
311
+ function flowAboveCharts(host: HTMLElement): Array<string> {
312
+ const layout: Array<string> = [];
313
+ for (const element of pathTo(host, chartsStandIn())) {
314
+ const siblingsBefore: Array<string> = [];
315
+ let sibling: Element | null = element.previousElementSibling;
316
+ while (sibling) {
317
+ if (!sibling.classList.contains("absolute")) {
318
+ siblingsBefore.unshift(
319
+ `${sibling.tagName}.${sibling.className || "-"}`,
320
+ );
321
+ }
322
+ sibling = sibling.previousElementSibling;
323
+ }
324
+ layout.push(
325
+ `${siblingsBefore.join(" + ") || "(first)"} > ${element.tagName}`,
326
+ );
327
+ }
328
+ return layout;
329
+ }
330
+
331
+ // Fetches started and not yet answered.
332
+ let pendingFetches: number = 0;
333
+
334
+ // Every fetch answers at once, with no data.
335
+ function answerFetches(): void {
336
+ fetchResultsMock.mockImplementation(() => {
337
+ pendingFetches++;
338
+ return Promise.resolve([{ data: [], truncated: false }]).then(
339
+ (results: Array<unknown>): Array<unknown> => {
340
+ pendingFetches--;
341
+ return results;
342
+ },
343
+ );
344
+ });
345
+ }
346
+
347
+ /*
348
+ * Until every fetch so far is answered and the charts are up: before its
349
+ * first answer lands, MetricView shows a loader in place of the charts,
350
+ * and a gesture must not land on charts about to be swapped out.
351
+ */
352
+ async function chartsSettled(): Promise<void> {
353
+ await waitFor(() => {
354
+ expect(fetchResultsMock).toHaveBeenCalled();
355
+ expect(pendingFetches).toBe(0);
356
+ expect(chartsStandIn()).toBeInTheDocument();
357
+ });
358
+ await act(async () => {
359
+ await Promise.resolve();
360
+ });
361
+ // waitFor ticks the fake clock; "now" is where a rolling window reads it.
362
+ jest.setSystemTime(NOW);
363
+ }
364
+
365
+ async function drag(): Promise<void> {
366
+ fireEvent.click(
367
+ await screen.findByRole("button", { name: "Drag across the chart" }),
368
+ );
369
+ await screen.findByTestId(RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID);
370
+ jest.setSystemTime(NOW);
371
+ }
372
+
373
+ async function doubleClick(): Promise<void> {
374
+ fireEvent.click(
375
+ await screen.findByRole("button", { name: "Double-click the chart" }),
376
+ );
377
+ await waitFor(() => {
378
+ expect(resetButton()).toBeNull();
379
+ });
380
+ jest.setSystemTime(NOW);
381
+ }
382
+
383
+ // Holds the next fetches open: MetricView is then refetching.
384
+ function holdFetches(): void {
385
+ fetchResultsMock.mockImplementation(() => {
386
+ return new Promise(() => {
387
+ // Intentionally never settles.
388
+ });
389
+ });
390
+ }
391
+
392
+ function refreshingIndicator(): HTMLElement | null {
393
+ return (
394
+ screen.queryAllByText("Refreshing").find((element: HTMLElement) => {
395
+ return element.tagName === "DIV";
396
+ }) || null
397
+ );
398
+ }
399
+
400
+ function fakePageZoom(isZoomed: boolean): TimeRangeZoom {
401
+ return {
402
+ isZoomed: isZoomed,
403
+ rangeBeforeZoom: isZoomed ? { range: TimeRange.PAST_ONE_HOUR } : null,
404
+ zoomToTimeRange: () => {},
405
+ resetZoom: () => {},
406
+ };
407
+ }
408
+
409
+ // A step as the forms hold it.
410
+ type FormStep = {
411
+ metricViewConfig: MetricsViewConfig;
412
+ rollingTime: RollingTime;
413
+ };
414
+
415
+ interface FormCase {
416
+ name: string;
417
+ // Every infrastructure form keeps its query builder on the Advanced tab.
418
+ opensOnAdvancedTab: boolean;
419
+ initial: FormStep;
420
+ form: React.FunctionComponent<any>;
421
+ stepProp: string;
422
+ }
423
+
424
+ function formCase(
425
+ name: string,
426
+ form: React.FunctionComponent<any>,
427
+ stepProp: string,
428
+ defaults: FormStep,
429
+ opensOnAdvancedTab: boolean,
430
+ ): FormCase {
431
+ return {
432
+ name: name,
433
+ opensOnAdvancedTab: opensOnAdvancedTab,
434
+ form: form,
435
+ stepProp: stepProp,
436
+ initial: {
437
+ ...defaults,
438
+ metricViewConfig: viewConfigFor(`form.${name}.cpu`),
439
+ rollingTime: RollingTime.Past1Hour,
440
+ },
441
+ };
442
+ }
443
+
444
+ const FORM_CASES: Array<FormCase> = [
445
+ formCase(
446
+ "Metric",
447
+ MetricMonitorStepForm,
448
+ "monitorStepMetricMonitor",
449
+ MonitorStepMetricMonitorUtil.getDefault(),
450
+ false,
451
+ ),
452
+ formCase(
453
+ "Host",
454
+ HostMonitorStepForm,
455
+ "monitorStepHostMonitor",
456
+ MonitorStepHostMonitorUtil.getDefault(),
457
+ true,
458
+ ),
459
+ formCase(
460
+ "Kubernetes",
461
+ KubernetesMonitorStepForm,
462
+ "monitorStepKubernetesMonitor",
463
+ MonitorStepKubernetesMonitorUtil.getDefault(),
464
+ true,
465
+ ),
466
+ formCase(
467
+ "Docker",
468
+ DockerMonitorStepForm,
469
+ "monitorStepDockerMonitor",
470
+ MonitorStepDockerMonitorUtil.getDefault(),
471
+ true,
472
+ ),
473
+ formCase(
474
+ "Docker Swarm",
475
+ DockerSwarmMonitorStepForm,
476
+ "monitorStepDockerSwarmMonitor",
477
+ MonitorStepDockerSwarmMonitorUtil.getDefault(),
478
+ true,
479
+ ),
480
+ formCase(
481
+ "Podman",
482
+ PodmanMonitorStepForm,
483
+ "monitorStepPodmanMonitor",
484
+ MonitorStepPodmanMonitorUtil.getDefault(),
485
+ true,
486
+ ),
487
+ formCase(
488
+ "Proxmox",
489
+ ProxmoxMonitorStepForm,
490
+ "monitorStepProxmoxMonitor",
491
+ MonitorStepProxmoxMonitorUtil.getDefault(),
492
+ true,
493
+ ),
494
+ formCase(
495
+ "VMware",
496
+ VMwareMonitorStepForm,
497
+ "monitorStepVMwareMonitor",
498
+ MonitorStepVMwareMonitorUtil.getDefault(),
499
+ true,
500
+ ),
501
+ formCase(
502
+ "Ceph",
503
+ CephMonitorStepForm,
504
+ "monitorStepCephMonitor",
505
+ MonitorStepCephMonitorUtil.getDefault(),
506
+ true,
507
+ ),
508
+ formCase(
509
+ "IoT",
510
+ IoTMonitorStepForm,
511
+ "monitorStepIoTMonitor",
512
+ MonitorStepIoTMonitorUtil.getDefault(),
513
+ true,
514
+ ),
515
+ ];
516
+
517
+ // The form's parent, as MonitorStep holds it.
518
+ const FormHost: React.FunctionComponent<{ formCase: FormCase }> = (props: {
519
+ formCase: FormCase;
520
+ }): React.ReactElement => {
521
+ const [step, setStep] = React.useState<FormStep>(props.formCase.initial);
522
+ return (
523
+ <div data-testid="host">
524
+ {React.createElement(props.formCase.form, {
525
+ [props.formCase.stepProp]: step,
526
+ onChange: setStep,
527
+ })}
528
+ </div>
529
+ );
530
+ };
531
+
532
+ async function renderForm(caseToRender: FormCase): Promise<HTMLElement> {
533
+ render(
534
+ <MemoryRouter>
535
+ <FormHost formCase={caseToRender} />
536
+ </MemoryRouter>,
537
+ );
538
+ if (caseToRender.opensOnAdvancedTab) {
539
+ fireEvent.click(await screen.findByRole("tab", { name: "Advanced" }));
540
+ }
541
+ await chartsSettled();
542
+ return screen.getByTestId("host");
543
+ }
544
+
545
+ beforeEach(() => {
546
+ jest.useFakeTimers({ doNotFake: ["nextTick", "setImmediate"] });
547
+ jest.setSystemTime(NOW);
548
+ getListMock.mockReset();
549
+ getItemMock.mockReset();
550
+ fetchResultsMock.mockReset();
551
+ getListMock.mockResolvedValue({ data: [], count: 0, skip: 0, limit: 0 });
552
+ getItemMock.mockResolvedValue(null);
553
+ pendingFetches = 0;
554
+ answerFetches();
555
+ });
556
+
557
+ afterEach(() => {
558
+ cleanup();
559
+ jest.useRealTimers();
560
+ });
561
+
562
+ describe.each(FORM_CASES)(
563
+ "the $name monitor form (the query builder shown)",
564
+ (caseToRender: FormCase) => {
565
+ test("Reset zoom appears at the end of the Charts heading, after the query builder and right above the chart", async () => {
566
+ await renderForm(caseToRender);
567
+
568
+ await drag();
569
+
570
+ const reset: HTMLElement = resetButton()!;
571
+ expect(reset.parentElement).toBe(chartsHeadingRow());
572
+ // Not above the query editors, where it used to be.
573
+ expect(
574
+ follows(reset, screen.getByRole("button", { name: "Add Metric" })),
575
+ ).toBe(true);
576
+ expect(follows(reset, screen.getAllByText("Queries")[0]!)).toBe(true);
577
+ expect(follows(chartsStandIn(), reset)).toBe(true);
578
+ expect(
579
+ screen.getAllByTestId(RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID),
580
+ ).toHaveLength(1);
581
+ });
582
+
583
+ test("a zoom and a reset add or remove nothing in the flow: the builder and the chart stay put", async () => {
584
+ const host: HTMLElement = await renderForm(caseToRender);
585
+ const headingRow: HTMLElement = chartsHeadingRow();
586
+ const before: Array<string> = flowAboveCharts(host);
587
+
588
+ await drag();
589
+ expect(flowAboveCharts(host)).toEqual(before);
590
+ // The row that holds it is the one that was already there.
591
+ expect(chartsHeadingRow()).toBe(headingRow);
592
+
593
+ await doubleClick();
594
+ expect(flowAboveCharts(host)).toEqual(before);
595
+ expect(chartsHeadingRow()).toBe(headingRow);
596
+ });
597
+
598
+ test("the button keeps the heading row's height, and none of its capitals", async () => {
599
+ await renderForm(caseToRender);
600
+
601
+ await drag();
602
+
603
+ const reset: HTMLElement = resetButton()!;
604
+ // -my-1: the 24px button inside the 16px row, which does not grow.
605
+ expect(reset).toHaveClass("-my-1");
606
+ expect(reset).toHaveClass("ml-auto");
607
+ expect(reset).toHaveClass("normal-case");
608
+ expect(reset).toHaveClass("tracking-normal");
609
+ expect(chartsHeadingRow()).toHaveClass("uppercase");
610
+ expect(screen.queryByTestId(OWN_ZOOM_CONTROLS_TEST_ID)).toBeNull();
611
+ });
612
+
613
+ test("it resets the preview, and goes when there is nothing left to reset", async () => {
614
+ await renderForm(caseToRender);
615
+ await drag();
616
+
617
+ fireEvent.click(resetButton()!);
618
+
619
+ await waitFor(() => {
620
+ expect(resetButton()).toBeNull();
621
+ });
622
+ // The heading stays, with nothing in it but its label.
623
+ expect(within(chartsHeadingRow()).queryByRole("button")).toBeNull();
624
+ });
625
+ },
626
+ );
627
+
628
+ describe("the Metric monitor form's refetch indicator", () => {
629
+ test("stays in the corner of the charts; the Reset is in the heading, so they never meet", async () => {
630
+ await renderForm(FORM_CASES[0]!);
631
+ holdFetches();
632
+
633
+ await drag();
634
+
635
+ const refreshing: HTMLElement | null = refreshingIndicator();
636
+ expect(refreshing).not.toBeNull();
637
+ expect(refreshing).toHaveClass("absolute");
638
+ expect(refreshing).toHaveClass("right-2");
639
+ expect(refreshing).toHaveClass("top-2");
640
+ expect(resetButton()!.parentElement).toBe(chartsHeadingRow());
641
+ });
642
+ });
643
+
644
+ /*
645
+ * The hosts without the builder: the incident and alert snapshots and the
646
+ * telemetry snapshot panel (charts in cards, localChartZoom), the monitor
647
+ * view's preview (cards, its own window), the Criteria page's step preview
648
+ * (no cards, localChartZoom) and the incident root cause chart (no cards,
649
+ * its own window).
650
+ */
651
+ interface BareHostCase {
652
+ name: string;
653
+ hideCardInCharts: boolean;
654
+ localChartZoom: boolean;
655
+ // Where the floating pair is centred: on the first chart's top border.
656
+ topClass: string;
657
+ }
658
+
659
+ const BARE_HOST_CASES: Array<BareHostCase> = [
660
+ {
661
+ name: "a snapshot (chart cards, local zoom)",
662
+ hideCardInCharts: false,
663
+ localChartZoom: true,
664
+ topClass: "top-0",
665
+ },
666
+ {
667
+ name: "the monitor view's preview (chart cards, its own window)",
668
+ hideCardInCharts: false,
669
+ localChartZoom: false,
670
+ topClass: "top-0",
671
+ },
672
+ {
673
+ name: "the Criteria page's step preview (no chart cards, local zoom)",
674
+ hideCardInCharts: true,
675
+ localChartZoom: true,
676
+ topClass: "top-[17px]",
677
+ },
678
+ {
679
+ name: "the incident root cause chart (no chart cards, its own window)",
680
+ hideCardInCharts: true,
681
+ localChartZoom: false,
682
+ topClass: "top-[17px]",
683
+ },
684
+ ];
685
+
686
+ const BareHost: React.FunctionComponent<{ hostCase: BareHostCase }> = (props: {
687
+ hostCase: BareHostCase;
688
+ }): React.ReactElement => {
689
+ const [data, setData] = React.useState<MetricViewData>(
690
+ viewDataFor("bare.cpu"),
691
+ );
692
+ return (
693
+ <div data-testid="host">
694
+ <MetricView
695
+ data={data}
696
+ hideQueryElements={true}
697
+ hideStartAndEndDate={true}
698
+ hideCardInCharts={props.hostCase.hideCardInCharts}
699
+ chartCssClass="rounded-lg border border-gray-200 shadow-sm"
700
+ {...(props.hostCase.localChartZoom ? { localChartZoom: true } : {})}
701
+ onChange={setData}
702
+ />
703
+ </div>
704
+ );
705
+ };
706
+
707
+ async function renderBareHost(hostCase: BareHostCase): Promise<HTMLElement> {
708
+ render(<BareHost hostCase={hostCase} />);
709
+ await chartsSettled();
710
+ return screen.getByTestId("host");
711
+ }
712
+
713
+ describe.each(BARE_HOST_CASES)(
714
+ "$name (no query builder)",
715
+ (hostCase: BareHostCase) => {
716
+ test("Reset zoom floats with the charts, out of the flow", async () => {
717
+ await renderBareHost(hostCase);
718
+
719
+ await drag();
720
+
721
+ const controls: HTMLElement = screen.getByTestId(
722
+ OWN_ZOOM_CONTROLS_TEST_ID,
723
+ );
724
+ expect(resetButton()!.parentElement).toBe(controls);
725
+ expect(controls).toHaveClass("absolute");
726
+ // With the charts: in the positioned box that holds them.
727
+ expect(controls.parentElement).toHaveClass("relative");
728
+ expect(controls.parentElement).toContainElement(chartsStandIn());
729
+ expect(
730
+ screen.getAllByTestId(RESET_TIME_RANGE_ZOOM_BUTTON_TEST_ID),
731
+ ).toHaveLength(1);
732
+ });
733
+
734
+ test("a zoom and a reset add or remove nothing in the flow: the chart stays put", async () => {
735
+ const host: HTMLElement = await renderBareHost(hostCase);
736
+ const before: Array<string> = flowAboveCharts(host);
737
+ const hostChildren: number = host.childElementCount;
738
+
739
+ await drag();
740
+ expect(flowAboveCharts(host)).toEqual(before);
741
+ expect(host.childElementCount).toBe(hostChildren);
742
+
743
+ await doubleClick();
744
+ expect(flowAboveCharts(host)).toEqual(before);
745
+ expect(host.childElementCount).toBe(hostChildren);
746
+ });
747
+
748
+ test("the pair is centred on the first chart's top border, clear of the chart's own title and hint", async () => {
749
+ await renderBareHost(hostCase);
750
+
751
+ await drag();
752
+
753
+ const controls: HTMLElement = screen.getByTestId(
754
+ OWN_ZOOM_CONTROLS_TEST_ID,
755
+ );
756
+ expect(controls).toHaveClass(hostCase.topClass);
757
+ expect(controls).toHaveClass("-translate-y-1/2");
758
+ expect(controls).toHaveClass("right-2");
759
+ });
760
+
761
+ test("only the button takes the pointer: a gesture anywhere else on the pair reaches the chart", async () => {
762
+ await renderBareHost(hostCase);
763
+
764
+ await drag();
765
+
766
+ expect(screen.getByTestId(OWN_ZOOM_CONTROLS_TEST_ID)).toHaveClass(
767
+ "pointer-events-none",
768
+ );
769
+ expect(resetButton()).toHaveClass("pointer-events-auto");
770
+ });
771
+
772
+ test("the refetch indicator sits beside the button, never under it", async () => {
773
+ await renderBareHost(hostCase);
774
+ holdFetches();
775
+
776
+ await drag();
777
+
778
+ const controls: HTMLElement = screen.getByTestId(
779
+ OWN_ZOOM_CONTROLS_TEST_ID,
780
+ );
781
+ const refreshing: HTMLElement | null = refreshingIndicator();
782
+ expect(refreshing).not.toBeNull();
783
+ expect(refreshing!.parentElement).toBe(controls);
784
+ // Placed by the pair, not on its own in the corner.
785
+ expect(refreshing).not.toHaveClass("absolute");
786
+ expect(follows(resetButton()!, refreshing!)).toBe(true);
787
+ });
788
+
789
+ test("before a zoom the pair offers no reset, and a double-click takes the reset away again", async () => {
790
+ await renderBareHost(hostCase);
791
+
792
+ expect(resetButton()).toBeNull();
793
+ expect(
794
+ within(screen.getByTestId(OWN_ZOOM_CONTROLS_TEST_ID)).queryByRole(
795
+ "button",
796
+ ),
797
+ ).toBeNull();
798
+
799
+ await drag();
800
+ await doubleClick();
801
+
802
+ expect(
803
+ within(screen.getByTestId(OWN_ZOOM_CONTROLS_TEST_ID)).queryByRole(
804
+ "button",
805
+ ),
806
+ ).toBeNull();
807
+ });
808
+
809
+ test("the button resets the charts' window", async () => {
810
+ await renderBareHost(hostCase);
811
+ await drag();
812
+ const zoomedFetches: number = fetchResultsMock.mock.calls.length;
813
+
814
+ fireEvent.click(resetButton()!);
815
+
816
+ await waitFor(() => {
817
+ expect(resetButton()).toBeNull();
818
+ });
819
+ expect(fetchResultsMock.mock.calls.length).toBeGreaterThan(zoomedFetches);
820
+ const lastWindow: InBetween<Date> = (
821
+ fetchResultsMock.mock.calls[
822
+ fetchResultsMock.mock.calls.length - 1
823
+ ]![0] as { metricViewData: MetricViewData }
824
+ ).metricViewData.startAndEndDate!;
825
+ expect(lastWindow.endValue.getTime()).toBe(NOW.getTime());
826
+ });
827
+ },
828
+ );
829
+
830
+ /*
831
+ * Where the view does not keep the zoom, whoever does offers the reset:
832
+ * a second one here would duplicate theirs.
833
+ */
834
+ describe("where the page or the host keeps the zoom, the view adds no Reset of its own", () => {
835
+ test("inside a zoomed page, with the query builder shown (the metric explorer)", async () => {
836
+ render(
837
+ <MemoryRouter>
838
+ <TimeRangeZoomProvider zoom={fakePageZoom(true)}>
839
+ <MetricView data={viewDataFor("explorer.cpu")} onChange={() => {}} />
840
+ </TimeRangeZoomProvider>
841
+ </MemoryRouter>,
842
+ );
843
+ await chartsSettled();
844
+
845
+ expect(resetButton()).toBeNull();
846
+ expect(within(chartsHeadingRow()).queryByRole("button")).toBeNull();
847
+ expect(screen.queryByTestId(OWN_ZOOM_CONTROLS_TEST_ID)).toBeNull();
848
+ });
849
+
850
+ test("inside a zoomed page, without the builder (the device health charts)", async () => {
851
+ render(
852
+ <TimeRangeZoomProvider zoom={fakePageZoom(true)}>
853
+ <MetricView
854
+ data={viewDataFor("device.cpu")}
855
+ hideQueryElements={true}
856
+ hideStartAndEndDate={true}
857
+ hideCardInCharts={true}
858
+ onChange={() => {}}
859
+ />
860
+ </TimeRangeZoomProvider>,
861
+ );
862
+ await chartsSettled();
863
+
864
+ expect(resetButton()).toBeNull();
865
+ expect(screen.queryByTestId(OWN_ZOOM_CONTROLS_TEST_ID)).toBeNull();
866
+ });
867
+
868
+ test("with the host's own handlers, even inside a zoomed page (an embedded metric card)", async () => {
869
+ render(
870
+ <TimeRangeZoomProvider zoom={fakePageZoom(true)}>
871
+ <MetricView
872
+ data={viewDataFor("card.cpu")}
873
+ hideQueryElements={true}
874
+ hideStartAndEndDate={true}
875
+ hideCardInCharts={true}
876
+ onChange={() => {}}
877
+ onTimeRangeSelect={() => {}}
878
+ onTimeRangeReset={() => {}}
879
+ />
880
+ </TimeRangeZoomProvider>,
881
+ );
882
+ await chartsSettled();
883
+
884
+ expect(resetButton()).toBeNull();
885
+ expect(screen.queryByTestId(OWN_ZOOM_CONTROLS_TEST_ID)).toBeNull();
886
+ });
887
+
888
+ test("with the zoom switched off", async () => {
889
+ render(
890
+ <TimeRangeZoomProvider zoom={fakePageZoom(true)}>
891
+ <MetricView
892
+ data={viewDataFor("off.cpu")}
893
+ hideQueryElements={true}
894
+ hideStartAndEndDate={true}
895
+ disableChartZoom={true}
896
+ onChange={() => {}}
897
+ />
898
+ </TimeRangeZoomProvider>,
899
+ );
900
+ await chartsSettled();
901
+
902
+ expect(resetButton()).toBeNull();
903
+ expect(screen.queryByTestId(OWN_ZOOM_CONTROLS_TEST_ID)).toBeNull();
904
+ });
905
+
906
+ test("there, the refetch indicator keeps its corner of the charts", async () => {
907
+ // The page's range, moved on by the page (a zoom, or its picker).
908
+ const PageHost: React.FunctionComponent = (): React.ReactElement => {
909
+ const [data, setData] = React.useState<MetricViewData>(
910
+ viewDataFor("device.cpu"),
911
+ );
912
+ return (
913
+ <TimeRangeZoomProvider zoom={fakePageZoom(true)}>
914
+ <button
915
+ type="button"
916
+ onClick={() => {
917
+ setData({
918
+ ...data,
919
+ startAndEndDate: new InBetween<Date>(MOCK_DRAG.start, NOW),
920
+ });
921
+ }}
922
+ >
923
+ Move the page range
924
+ </button>
925
+ <MetricView
926
+ data={data}
927
+ hideQueryElements={true}
928
+ hideStartAndEndDate={true}
929
+ hideCardInCharts={true}
930
+ onChange={setData}
931
+ />
932
+ </TimeRangeZoomProvider>
933
+ );
934
+ };
935
+ render(<PageHost />);
936
+ await chartsSettled();
937
+ holdFetches();
938
+
939
+ act(() => {
940
+ fireEvent.click(
941
+ screen.getByRole("button", { name: "Move the page range" }),
942
+ );
943
+ });
944
+
945
+ const refreshing: HTMLElement | null = refreshingIndicator();
946
+ expect(refreshing).not.toBeNull();
947
+ expect(refreshing).toHaveClass("absolute");
948
+ expect(refreshing).toHaveClass("right-2");
949
+ expect(refreshing).toHaveClass("top-2");
950
+ expect(screen.queryByTestId(OWN_ZOOM_CONTROLS_TEST_ID)).toBeNull();
951
+ });
952
+ });