@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,918 @@
1
+ /** @timezone UTC */
2
+ import "@testing-library/jest-dom";
3
+ import { afterEach, beforeEach, describe, expect, test } from "@jest/globals";
4
+ import { act, cleanup, fireEvent, render } from "@testing-library/react";
5
+ import React from "react";
6
+ import getJestMockFunction, { MockFunction } from "../../../MockType";
7
+
8
+ /*
9
+ * Drag-to-zoom and the double-click reset, driven through REAL recharts
10
+ * (issue #4105: a drag across any chart zooms the page to that slice, a
11
+ * double-click on any chart puts it back).
12
+ *
13
+ * The other drag suites stand in for recharts' chart root and hand the
14
+ * chart's handlers a made-up {activeTooltipIndex}. That skips the layer
15
+ * this suite is about: recharts works out the bucket under the pointer in
16
+ * its own store, and hands the chart's mousedown / mousemove / mouseup
17
+ * handlers whatever that store holds at that moment - holding some events
18
+ * back for the next animation frame. A recharts upgrade that renamed that
19
+ * field, or changed when it is filled in, would break the zoom on every
20
+ * chart in the product while every stand-in suite stayed green.
21
+ *
22
+ * So here only ResponsiveContainer is stood in for: it measures its parent,
23
+ * which jsdom always reports as 0x0, and would draw nothing. The pointer
24
+ * goes to the plot at the x recharts drew each bucket's tick label at, and
25
+ * recharts resolves it to a bucket itself (jsdom has no layout, so the
26
+ * chart's box sits at 0,0 and a clientX is an x inside the chart).
27
+ *
28
+ * No test lets an animation frame pass unless it says so. A chart that
29
+ * offers a drag takes mousemove unthrottled, so every move is in recharts'
30
+ * store before the next event arrives; were mousemove held for the next
31
+ * frame again, a press here would find no bucket under the pointer yet and
32
+ * most of this suite would fail. The timing tests let frames pass between
33
+ * some events and not others, the way a real hand does: a slow drag works
34
+ * either way, but a held mousemove ends a quick flick a bucket or more
35
+ * short, and starts a press made in the frame the pointer arrived a bucket
36
+ * early - then drops it, when the move that brought the pointer there (no
37
+ * button held yet) lands after the press.
38
+ */
39
+
40
+ jest.mock("recharts", () => {
41
+ const actual: Record<string, any> = jest.requireActual("recharts");
42
+ const react: typeof React = jest.requireActual("react") as typeof React;
43
+ return {
44
+ ...actual,
45
+ ResponsiveContainer: ({ children }: { children: React.ReactElement }) => {
46
+ return react.cloneElement(children, { width: 600, height: 300 });
47
+ },
48
+ };
49
+ });
50
+
51
+ import { AreaChart } from "../../../../UI/Components/Charts/ChartLibrary/AreaChart/AreaChart";
52
+ import { BarChart } from "../../../../UI/Components/Charts/ChartLibrary/BarChart/BarChart";
53
+ import { LineChart } from "../../../../UI/Components/Charts/ChartLibrary/LineChart/LineChart";
54
+ import {
55
+ CHART_DATA_POINT_DATE_KEY,
56
+ CHART_DATA_POINT_X_AXIS_KEY,
57
+ } from "../../../../UI/Components/Charts/ChartLibrary/Types/ChartDataPoint";
58
+ import { DOUBLE_CLICK_DISAMBIGUATION_MS } from "../../../../UI/Components/Charts/ChartLibrary/Utils/DoubleClick";
59
+ import AreaChartElement from "../../../../UI/Components/Charts/Area/AreaChart";
60
+ import BarChartElement from "../../../../UI/Components/Charts/Bar/BarChart";
61
+ import LineChartElement from "../../../../UI/Components/Charts/Line/LineChart";
62
+ import ChartCurve from "../../../../UI/Components/Charts/Types/ChartCurve";
63
+ import SeriesPoint from "../../../../UI/Components/Charts/Types/SeriesPoints";
64
+ import {
65
+ XAxis as ChartXAxis,
66
+ XAxisAggregateType,
67
+ } from "../../../../UI/Components/Charts/Types/XAxis/XAxis";
68
+ import XAxisPrecision from "../../../../UI/Components/Charts/Types/XAxis/XAxisPrecision";
69
+ import XAxisType from "../../../../UI/Components/Charts/Types/XAxis/XAxisType";
70
+ import YAxis, {
71
+ YAxisPrecision,
72
+ } from "../../../../UI/Components/Charts/Types/YAxis/YAxis";
73
+ import YAxisType from "../../../../UI/Components/Charts/Types/YAxis/YAxisType";
74
+
75
+ const MINUTE_MS: number = 60 * 1000;
76
+ // One animation frame, as fake timers run them.
77
+ const FRAME_MS: number = 16;
78
+ const FIRST_BUCKET_MS: number = Date.parse("2026-09-28T10:00:00.000Z");
79
+ // Inside the plot: below its top edge and above the x-axis.
80
+ const PLOT_Y: number = 120;
81
+ // Somewhere on the page, well away from the chart.
82
+ const OFF_CHART: { clientX: number; clientY: number } = {
83
+ clientX: 900,
84
+ clientY: 520,
85
+ };
86
+
87
+ /*
88
+ * Ten one-minute buckets, 10:00 to 10:09, in the shape the time-series
89
+ * wrappers hand the cores: the label recharts draws, the start of the
90
+ * bucket the row draws, and one value per series.
91
+ */
92
+ const ROWS: Array<Record<string, number | string>> = Array.from(
93
+ { length: 10 },
94
+ (_: unknown, index: number): Record<string, number | string> => {
95
+ return {
96
+ [CHART_DATA_POINT_X_AXIS_KEY]: `10:0${index}`,
97
+ [CHART_DATA_POINT_DATE_KEY]: FIRST_BUCKET_MS + index * MINUTE_MS,
98
+ CPU: 40 + index,
99
+ };
100
+ },
101
+ );
102
+
103
+ type SelectHandler = (startTime: Date, endTime: Date) => void;
104
+
105
+ type BucketClickHandler = (
106
+ bucketStart: Date,
107
+ bucketEnd: Date,
108
+ valuesAtBucket: Record<string, number | string>,
109
+ ) => void;
110
+
111
+ interface ChartHandlers {
112
+ onTimeRangeSelect?: SelectHandler | undefined;
113
+ onTimeRangeReset?: (() => void) | undefined;
114
+ onBucketClick?: BucketClickHandler | undefined;
115
+ }
116
+
117
+ interface ChartUnderTest {
118
+ name: string;
119
+ /*
120
+ * How recharts places a bucket on the x-axis: at a point (line, area),
121
+ * or across a band holding the bar and the gap around it (bar).
122
+ */
123
+ scale: "point" | "band";
124
+ // Whether a plain click on the plot reports the bucket under it.
125
+ reportsBucketClicks: boolean;
126
+ render: (handlers: ChartHandlers) => React.ReactElement;
127
+ }
128
+
129
+ const CORES: Array<ChartUnderTest> = [
130
+ {
131
+ name: "line",
132
+ scale: "point",
133
+ reportsBucketClicks: true,
134
+ render: (handlers: ChartHandlers): React.ReactElement => {
135
+ return (
136
+ <LineChart
137
+ data={ROWS}
138
+ index={CHART_DATA_POINT_X_AXIS_KEY}
139
+ categories={["CPU"]}
140
+ showLegend={false}
141
+ onTimeRangeSelect={handlers.onTimeRangeSelect}
142
+ onTimeRangeReset={handlers.onTimeRangeReset}
143
+ onBucketClick={handlers.onBucketClick}
144
+ />
145
+ );
146
+ },
147
+ },
148
+ {
149
+ name: "area",
150
+ scale: "point",
151
+ reportsBucketClicks: true,
152
+ render: (handlers: ChartHandlers): React.ReactElement => {
153
+ return (
154
+ <AreaChart
155
+ data={ROWS}
156
+ index={CHART_DATA_POINT_X_AXIS_KEY}
157
+ categories={["CPU"]}
158
+ showLegend={false}
159
+ onTimeRangeSelect={handlers.onTimeRangeSelect}
160
+ onTimeRangeReset={handlers.onTimeRangeReset}
161
+ onBucketClick={handlers.onBucketClick}
162
+ />
163
+ );
164
+ },
165
+ },
166
+ {
167
+ name: "bar",
168
+ scale: "band",
169
+ reportsBucketClicks: false,
170
+ render: (handlers: ChartHandlers): React.ReactElement => {
171
+ return (
172
+ <BarChart
173
+ data={ROWS}
174
+ index={CHART_DATA_POINT_X_AXIS_KEY}
175
+ categories={["CPU"]}
176
+ showLegend={false}
177
+ onTimeRangeSelect={handlers.onTimeRangeSelect}
178
+ onTimeRangeReset={handlers.onTimeRangeReset}
179
+ />
180
+ );
181
+ },
182
+ },
183
+ ];
184
+
185
+ let renderedChart: HTMLElement | null = null;
186
+
187
+ // Renders a chart the gestures below then act on.
188
+ function renderChartElement(chart: React.ReactElement): void {
189
+ renderedChart = render(chart).container;
190
+ }
191
+
192
+ function renderChart(chart: ChartUnderTest, handlers: ChartHandlers): void {
193
+ renderChartElement(chart.render(handlers));
194
+ }
195
+
196
+ function chartContainer(): HTMLElement {
197
+ if (!renderedChart) {
198
+ throw new Error("no chart rendered");
199
+ }
200
+ return renderedChart;
201
+ }
202
+
203
+ // The element recharts listens on; every mouse event below bubbles to it.
204
+ function chartWrapper(): Element {
205
+ const wrapper: Element | null =
206
+ chartContainer().querySelector(".recharts-wrapper");
207
+ if (!wrapper) {
208
+ throw new Error("recharts drew no chart");
209
+ }
210
+ return wrapper;
211
+ }
212
+
213
+ /*
214
+ * The plot's own background: where the pointer lands when it is over no
215
+ * line, area or bar. The events fired at it bubble to the wrapper.
216
+ */
217
+ function plotSurface(): Element {
218
+ const surface: Element | null = chartContainer().querySelector(
219
+ "svg.recharts-surface",
220
+ );
221
+ if (!surface) {
222
+ throw new Error("recharts drew no plot surface");
223
+ }
224
+ return surface;
225
+ }
226
+
227
+ /*
228
+ * The pointer x that lands on a bucket: where recharts drew its tick
229
+ * label, the centre of the bucket on both kinds of axis.
230
+ */
231
+ function tickX(label: string): number {
232
+ const tick: Element | undefined = Array.from(
233
+ chartContainer().querySelectorAll(
234
+ ".recharts-xAxis-tick-labels text.recharts-cartesian-axis-tick-value",
235
+ ),
236
+ ).find((element: Element): boolean => {
237
+ return element.textContent === label;
238
+ });
239
+ if (!tick) {
240
+ throw new Error(`recharts drew no tick label "${label}"`);
241
+ }
242
+ return Number(tick.getAttribute("x"));
243
+ }
244
+
245
+ // The pointer arrives over a bucket with no button held.
246
+ function hover(label: string): void {
247
+ fireEvent.mouseMove(plotSurface(), {
248
+ clientX: tickX(label),
249
+ clientY: PLOT_Y,
250
+ buttons: 0,
251
+ });
252
+ }
253
+
254
+ // The main button goes down where the pointer already is.
255
+ function press(label: string): void {
256
+ fireEvent.mouseDown(plotSurface(), {
257
+ clientX: tickX(label),
258
+ clientY: PLOT_Y,
259
+ button: 0,
260
+ buttons: 1,
261
+ });
262
+ }
263
+
264
+ /*
265
+ * The main button goes down over a bucket in the same frame the pointer
266
+ * arrived there: a browser always moves the pointer to a spot before it
267
+ * reports a press on it.
268
+ */
269
+ function pressAt(label: string): void {
270
+ hover(label);
271
+ press(label);
272
+ }
273
+
274
+ // The pointer moves over a bucket with the main button held.
275
+ function dragTo(label: string): void {
276
+ fireEvent.mouseMove(plotSurface(), {
277
+ clientX: tickX(label),
278
+ clientY: PLOT_Y,
279
+ buttons: 1,
280
+ });
281
+ }
282
+
283
+ /*
284
+ * The button comes up over a bucket of the chart. The browser follows it
285
+ * with a click on the plot, as it does whenever the press and the release
286
+ * both land inside it.
287
+ */
288
+ function releaseAt(label: string): void {
289
+ fireEvent.mouseUp(plotSurface(), {
290
+ clientX: tickX(label),
291
+ clientY: PLOT_Y,
292
+ button: 0,
293
+ buttons: 0,
294
+ });
295
+ fireEvent.click(plotSurface(), {
296
+ clientX: tickX(label),
297
+ clientY: PLOT_Y,
298
+ button: 0,
299
+ detail: 1,
300
+ });
301
+ }
302
+
303
+ /*
304
+ * The pointer leaves the chart with the button held, wanders the page and
305
+ * lets go there: only the page hears that release, never the chart.
306
+ */
307
+ function releaseOnThePage(): void {
308
+ fireEvent.mouseLeave(chartWrapper(), {
309
+ relatedTarget: document.body,
310
+ ...OFF_CHART,
311
+ buttons: 1,
312
+ });
313
+ fireEvent.mouseMove(document.body, { ...OFF_CHART, buttons: 1 });
314
+ fireEvent.mouseUp(document.body, { ...OFF_CHART, button: 0, buttons: 0 });
315
+ }
316
+
317
+ // What a browser delivers for a double-click at one spot of the plot.
318
+ function doubleClickAt(label: string): void {
319
+ const spot: { clientX: number; clientY: number } = {
320
+ clientX: tickX(label),
321
+ clientY: PLOT_Y,
322
+ };
323
+ hover(label);
324
+ for (const detail of [1, 2]) {
325
+ fireEvent.mouseDown(plotSurface(), {
326
+ ...spot,
327
+ button: 0,
328
+ buttons: 1,
329
+ detail: detail,
330
+ });
331
+ fireEvent.mouseUp(plotSurface(), {
332
+ ...spot,
333
+ button: 0,
334
+ buttons: 0,
335
+ detail: detail,
336
+ });
337
+ fireEvent.click(plotSurface(), { ...spot, button: 0, detail: detail });
338
+ }
339
+ fireEvent.doubleClick(plotSurface(), { ...spot, button: 0, detail: 2 });
340
+ }
341
+
342
+ // Lets one animation frame pass: fake timers run the frame's callbacks.
343
+ function nextFrame(): void {
344
+ act(() => {
345
+ jest.advanceTimersByTime(FRAME_MS);
346
+ });
347
+ }
348
+
349
+ function waitOutTheDoubleClickWindow(): void {
350
+ act(() => {
351
+ jest.advanceTimersByTime(DOUBLE_CLICK_DISAMBIGUATION_MS * 2);
352
+ });
353
+ }
354
+
355
+ // "10:02" -> the instant that minute starts, as the handlers report it.
356
+ function at(label: string): string {
357
+ return `2026-09-28T${label}:00.000Z`;
358
+ }
359
+
360
+ function zoomWindow(from: string, to: string): [string, string] {
361
+ return [at(from), at(to)];
362
+ }
363
+
364
+ // Every window the chart selected, oldest first.
365
+ function selections(onTimeRangeSelect: MockFunction): Array<[string, string]> {
366
+ return onTimeRangeSelect.mock.calls.map(
367
+ (call: Array<unknown>): [string, string] => {
368
+ return [(call[0] as Date).toISOString(), (call[1] as Date).toISOString()];
369
+ },
370
+ );
371
+ }
372
+
373
+ interface BandEdges {
374
+ left: number;
375
+ right: number;
376
+ }
377
+
378
+ // The live selection band recharts drew, or null.
379
+ function drawnBand(): BandEdges | null {
380
+ const rect: Element | null = chartContainer().querySelector(
381
+ ".recharts-reference-area-rect",
382
+ );
383
+ if (!rect) {
384
+ return null;
385
+ }
386
+ const left: number = Number(rect.getAttribute("x"));
387
+ return { left: left, right: left + Number(rect.getAttribute("width")) };
388
+ }
389
+
390
+ /*
391
+ * Where a band over the buckets lower..upper belongs: from the first
392
+ * bucket's point to the last one's on a line or an area chart, and over
393
+ * the whole of both end bars (with the gaps around them) on a bar chart.
394
+ */
395
+ function expectBandOver(
396
+ chart: ChartUnderTest,
397
+ lower: string,
398
+ upper: string,
399
+ ): void {
400
+ const band: BandEdges | null = drawnBand();
401
+ expect(band).not.toBeNull();
402
+
403
+ const halfBucket: number =
404
+ chart.scale === "band" ? (tickX("10:01") - tickX("10:00")) / 2 : 0;
405
+ expect(band!.left).toBeCloseTo(tickX(lower) - halfBucket, 1);
406
+ expect(band!.right).toBeCloseTo(tickX(upper) + halfBucket, 1);
407
+ }
408
+
409
+ beforeEach(() => {
410
+ /*
411
+ * Installed AT the fixed time rather than moved there with setSystemTime:
412
+ * fake timers count animation frames from the moment they are installed,
413
+ * and a clock moved back after that puts the next frame up to 31ms out,
414
+ * so nextFrame() would not always run one.
415
+ */
416
+ jest.useFakeTimers({ now: new Date("2026-09-28T10:30:00.000Z") });
417
+ });
418
+
419
+ afterEach(() => {
420
+ cleanup();
421
+ renderedChart = null;
422
+ jest.useRealTimers();
423
+ });
424
+
425
+ describe("drag-to-zoom through real recharts", () => {
426
+ for (const chart of CORES) {
427
+ describe(`the ${chart.name} chart`, () => {
428
+ test("a left-to-right drag selects from the start of the first bucket to the end of the last", () => {
429
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
430
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
431
+
432
+ pressAt("10:02");
433
+ dragTo("10:03");
434
+ dragTo("10:04");
435
+ dragTo("10:06");
436
+ releaseAt("10:06");
437
+
438
+ /*
439
+ * Exactly once: the page-wide listener that catches a release off
440
+ * the chart must not commit the chart's own release a second time.
441
+ */
442
+ expect(selections(onTimeRangeSelect)).toEqual([
443
+ zoomWindow("10:02", "10:07"),
444
+ ]);
445
+ });
446
+
447
+ test("a right-to-left drag selects the same window", () => {
448
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
449
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
450
+
451
+ pressAt("10:06");
452
+ dragTo("10:05");
453
+ dragTo("10:03");
454
+ dragTo("10:02");
455
+ releaseAt("10:02");
456
+
457
+ expect(selections(onTimeRangeSelect)).toEqual([
458
+ zoomWindow("10:02", "10:07"),
459
+ ]);
460
+ });
461
+
462
+ test("a drag that doubles back selects up to where it was released, not its furthest reach", () => {
463
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
464
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
465
+
466
+ pressAt("10:02");
467
+ dragTo("10:07");
468
+ dragTo("10:04");
469
+ releaseAt("10:04");
470
+
471
+ expect(selections(onTimeRangeSelect)).toEqual([
472
+ zoomWindow("10:02", "10:05"),
473
+ ]);
474
+ });
475
+
476
+ test("a drag to the last bucket takes its width from the bucket before it", () => {
477
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
478
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
479
+
480
+ pressAt("10:07");
481
+ dragTo("10:09");
482
+ releaseAt("10:09");
483
+
484
+ expect(selections(onTimeRangeSelect)).toEqual([
485
+ ["2026-09-28T10:07:00.000Z", "2026-09-28T10:10:00.000Z"],
486
+ ]);
487
+ });
488
+
489
+ test("the band draws nothing on the press, then covers every bucket crossed and clears on the release", () => {
490
+ renderChart(chart, { onTimeRangeSelect: getJestMockFunction() });
491
+
492
+ pressAt("10:03");
493
+ expect(drawnBand()).toBeNull();
494
+
495
+ dragTo("10:06");
496
+ expectBandOver(chart, "10:03", "10:06");
497
+
498
+ dragTo("10:04");
499
+ expectBandOver(chart, "10:03", "10:04");
500
+
501
+ releaseAt("10:04");
502
+ expect(drawnBand()).toBeNull();
503
+ });
504
+
505
+ test("a right-to-left drag's band covers both end buckets too", () => {
506
+ renderChart(chart, { onTimeRangeSelect: getJestMockFunction() });
507
+
508
+ pressAt("10:06");
509
+ dragTo("10:05");
510
+ expectBandOver(chart, "10:05", "10:06");
511
+
512
+ dragTo("10:03");
513
+ expectBandOver(chart, "10:03", "10:06");
514
+
515
+ releaseAt("10:03");
516
+ expect(drawnBand()).toBeNull();
517
+ });
518
+
519
+ test("a drag released outside the chart, on the page, still selects up to the last bucket it reached", () => {
520
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
521
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
522
+
523
+ pressAt("10:02");
524
+ dragTo("10:04");
525
+ dragTo("10:06");
526
+ releaseOnThePage();
527
+
528
+ expect(selections(onTimeRangeSelect)).toEqual([
529
+ zoomWindow("10:02", "10:07"),
530
+ ]);
531
+ expect(drawnBand()).toBeNull();
532
+
533
+ // That release ended the press: another one on the page selects nothing.
534
+ fireEvent.mouseUp(document.body, { ...OFF_CHART, button: 0 });
535
+ expect(onTimeRangeSelect).toHaveBeenCalledTimes(1);
536
+ });
537
+
538
+ test("a right-to-left drag released on the page selects the same window", () => {
539
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
540
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
541
+
542
+ pressAt("10:06");
543
+ dragTo("10:04");
544
+ dragTo("10:02");
545
+ releaseOnThePage();
546
+
547
+ expect(selections(onTimeRangeSelect)).toEqual([
548
+ zoomWindow("10:02", "10:07"),
549
+ ]);
550
+ });
551
+
552
+ test("a press and release on one bucket selects nothing and draws no band", () => {
553
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
554
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
555
+
556
+ pressAt("10:04");
557
+ // A hand never holds perfectly still: a nudge inside the bucket.
558
+ fireEvent.mouseMove(plotSurface(), {
559
+ clientX: tickX("10:04") + 3,
560
+ clientY: PLOT_Y + 2,
561
+ buttons: 1,
562
+ });
563
+ expect(drawnBand()).toBeNull();
564
+ releaseAt("10:04");
565
+
566
+ expect(onTimeRangeSelect).not.toHaveBeenCalled();
567
+ expect(drawnBand()).toBeNull();
568
+ });
569
+
570
+ test("a press on one bucket released on the page selects nothing", () => {
571
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
572
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
573
+
574
+ pressAt("10:04");
575
+ releaseOnThePage();
576
+
577
+ expect(onTimeRangeSelect).not.toHaveBeenCalled();
578
+ });
579
+
580
+ test("a drag whose button came up where no page could hear it is dropped at its next move", () => {
581
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
582
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
583
+
584
+ pressAt("10:02");
585
+ dragTo("10:05");
586
+ expect(drawnBand()).not.toBeNull();
587
+
588
+ // Back over the chart with no button held.
589
+ hover("10:06");
590
+ expect(drawnBand()).toBeNull();
591
+
592
+ fireEvent.mouseUp(document.body, { ...OFF_CHART, button: 0 });
593
+ expect(onTimeRangeSelect).not.toHaveBeenCalled();
594
+ });
595
+
596
+ test("a right-button drag selects nothing", () => {
597
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
598
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
599
+
600
+ hover("10:02");
601
+ fireEvent.mouseDown(plotSurface(), {
602
+ clientX: tickX("10:02"),
603
+ clientY: PLOT_Y,
604
+ button: 2,
605
+ buttons: 2,
606
+ });
607
+ fireEvent.mouseMove(plotSurface(), {
608
+ clientX: tickX("10:05"),
609
+ clientY: PLOT_Y,
610
+ buttons: 2,
611
+ });
612
+ expect(drawnBand()).toBeNull();
613
+ fireEvent.mouseUp(plotSurface(), {
614
+ clientX: tickX("10:05"),
615
+ clientY: PLOT_Y,
616
+ button: 2,
617
+ });
618
+
619
+ expect(onTimeRangeSelect).not.toHaveBeenCalled();
620
+ });
621
+
622
+ test("a double-click on an empty spot of the plot resets the zoom, and selects nothing", () => {
623
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
624
+ const onTimeRangeReset: MockFunction = getJestMockFunction();
625
+ const onBucketClick: MockFunction = getJestMockFunction();
626
+ renderChart(chart, {
627
+ onTimeRangeSelect: onTimeRangeSelect,
628
+ onTimeRangeReset: onTimeRangeReset,
629
+ onBucketClick: onBucketClick,
630
+ });
631
+
632
+ doubleClickAt("10:04");
633
+
634
+ expect(onTimeRangeReset).toHaveBeenCalledTimes(1);
635
+ waitOutTheDoubleClickWindow();
636
+ // Neither click of the double-click did anything on its way past.
637
+ expect(onBucketClick).not.toHaveBeenCalled();
638
+ expect(onTimeRangeSelect).not.toHaveBeenCalled();
639
+ expect(drawnBand()).toBeNull();
640
+ });
641
+
642
+ test("the reset double-click still works right after a drag", () => {
643
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
644
+ const onTimeRangeReset: MockFunction = getJestMockFunction();
645
+ renderChart(chart, {
646
+ onTimeRangeSelect: onTimeRangeSelect,
647
+ onTimeRangeReset: onTimeRangeReset,
648
+ });
649
+
650
+ pressAt("10:02");
651
+ dragTo("10:05");
652
+ releaseAt("10:05");
653
+ doubleClickAt("10:05");
654
+
655
+ expect(selections(onTimeRangeSelect)).toEqual([
656
+ zoomWindow("10:02", "10:06"),
657
+ ]);
658
+ expect(onTimeRangeReset).toHaveBeenCalledTimes(1);
659
+ });
660
+
661
+ if (chart.reportsBucketClicks) {
662
+ test("a single click reports the bucket under the pointer once the double-click window has passed", () => {
663
+ const onBucketClick: MockFunction = getJestMockFunction();
664
+ renderChart(chart, {
665
+ onTimeRangeSelect: getJestMockFunction(),
666
+ onTimeRangeReset: getJestMockFunction(),
667
+ onBucketClick: onBucketClick,
668
+ });
669
+
670
+ pressAt("10:04");
671
+ releaseAt("10:04");
672
+ expect(onBucketClick).not.toHaveBeenCalled();
673
+
674
+ act(() => {
675
+ jest.advanceTimersByTime(DOUBLE_CLICK_DISAMBIGUATION_MS);
676
+ });
677
+ expect(onBucketClick).toHaveBeenCalledTimes(1);
678
+ expect((onBucketClick.mock.calls[0]![0] as Date).toISOString()).toBe(
679
+ at("10:04"),
680
+ );
681
+ expect((onBucketClick.mock.calls[0]![1] as Date).toISOString()).toBe(
682
+ at("10:05"),
683
+ );
684
+ expect(onBucketClick.mock.calls[0]![2]).toMatchObject({ CPU: 44 });
685
+ });
686
+
687
+ test("the click a browser fires after a drag's release reports no bucket", () => {
688
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
689
+ const onBucketClick: MockFunction = getJestMockFunction();
690
+ renderChart(chart, {
691
+ onTimeRangeSelect: onTimeRangeSelect,
692
+ onTimeRangeReset: getJestMockFunction(),
693
+ onBucketClick: onBucketClick,
694
+ });
695
+
696
+ pressAt("10:02");
697
+ dragTo("10:05");
698
+ releaseAt("10:05");
699
+ waitOutTheDoubleClickWindow();
700
+
701
+ expect(onTimeRangeSelect).toHaveBeenCalledTimes(1);
702
+ expect(onBucketClick).not.toHaveBeenCalled();
703
+ });
704
+ }
705
+ });
706
+ }
707
+ });
708
+
709
+ describe("drag-to-zoom through real recharts, frame by frame", () => {
710
+ for (const chart of CORES) {
711
+ describe(`the ${chart.name} chart`, () => {
712
+ test("a slow drag, the pointer resting a frame before every press, move and release, selects the buckets it crossed", () => {
713
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
714
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
715
+
716
+ hover("10:02");
717
+ nextFrame();
718
+ press("10:02");
719
+ nextFrame();
720
+ dragTo("10:04");
721
+ nextFrame();
722
+ dragTo("10:06");
723
+ nextFrame();
724
+ releaseAt("10:06");
725
+ nextFrame();
726
+
727
+ expect(selections(onTimeRangeSelect)).toEqual([
728
+ zoomWindow("10:02", "10:07"),
729
+ ]);
730
+ });
731
+
732
+ test("a quick flick released in the frame of its last move still covers the bucket it was released on", () => {
733
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
734
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
735
+
736
+ hover("10:02");
737
+ nextFrame();
738
+ press("10:02");
739
+ nextFrame();
740
+ dragTo("10:03");
741
+ nextFrame();
742
+ // The last move and the release land in the same frame.
743
+ dragTo("10:06");
744
+ releaseAt("10:06");
745
+
746
+ expect(selections(onTimeRangeSelect)).toEqual([
747
+ zoomWindow("10:02", "10:07"),
748
+ ]);
749
+ });
750
+
751
+ test("a press in the frame the pointer arrived starts on the bucket it arrived at, and holds", () => {
752
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
753
+ renderChart(chart, { onTimeRangeSelect: onTimeRangeSelect });
754
+
755
+ // The pointer rests on 10:01 a while, then darts to 10:02 and presses.
756
+ hover("10:01");
757
+ nextFrame();
758
+ pressAt("10:02");
759
+ /*
760
+ * A frame passes with the button held: the move that brought the
761
+ * pointer here (no button held yet) must not land now and read as
762
+ * the button coming up.
763
+ */
764
+ nextFrame();
765
+ dragTo("10:05");
766
+ nextFrame();
767
+ releaseAt("10:05");
768
+
769
+ expect(selections(onTimeRangeSelect)).toEqual([
770
+ zoomWindow("10:02", "10:06"),
771
+ ]);
772
+ });
773
+ });
774
+ }
775
+ });
776
+
777
+ /*
778
+ * The whole chain a page renders: series points, the rows the chart
779
+ * elements build from them, real recharts, the core's drag. A rolling range
780
+ * is resolved at an instant off the minute (10:23:11 here), so the window
781
+ * starts at 10:08:11 while each row draws a whole minute from 10:08 on.
782
+ * The zoom must be exactly the minutes under the pointer.
783
+ */
784
+ describe("drag-to-zoom through the chart elements a page renders", () => {
785
+ const windowEnd: Date = new Date("2026-09-28T10:23:11.000Z");
786
+ const windowStart: Date = new Date(windowEnd.getTime() - 15 * MINUTE_MS);
787
+
788
+ const xAxis: ChartXAxis = {
789
+ legend: "Time",
790
+ options: {
791
+ type: XAxisType.Time,
792
+ min: windowStart,
793
+ max: windowEnd,
794
+ aggregateType: XAxisAggregateType.Average,
795
+ precision: XAxisPrecision.EVERY_MINUTE,
796
+ },
797
+ };
798
+
799
+ const yAxis: YAxis = {
800
+ legend: "%",
801
+ options: {
802
+ type: YAxisType.Number,
803
+ min: 0,
804
+ max: 200,
805
+ precision: YAxisPrecision.NoDecimals,
806
+ formatter: (value: number): string => {
807
+ return `${value}%`;
808
+ },
809
+ },
810
+ };
811
+
812
+ // One point at the start of every minute, as the analytics server returns them.
813
+ const series: Array<SeriesPoint> = [
814
+ {
815
+ seriesName: "CPU",
816
+ data: Array.from({ length: 16 }, (_: unknown, index: number) => {
817
+ return {
818
+ x: new Date(
819
+ Date.parse("2026-09-28T10:08:00.000Z") + index * MINUTE_MS,
820
+ ),
821
+ y: 40 + index,
822
+ };
823
+ }),
824
+ },
825
+ ];
826
+
827
+ const elements: Array<{
828
+ name: string;
829
+ render: (onTimeRangeSelect: SelectHandler) => React.ReactElement;
830
+ }> = [
831
+ {
832
+ name: "line",
833
+ render: (onTimeRangeSelect: SelectHandler): React.ReactElement => {
834
+ return (
835
+ <LineChartElement
836
+ data={series}
837
+ xAxis={xAxis}
838
+ yAxis={yAxis}
839
+ curve={ChartCurve.LINEAR}
840
+ heightInPx={300}
841
+ showLegend={false}
842
+ sync={false}
843
+ syncid="real-recharts-drag-line"
844
+ onTimeRangeSelect={onTimeRangeSelect}
845
+ />
846
+ );
847
+ },
848
+ },
849
+ {
850
+ name: "area",
851
+ render: (onTimeRangeSelect: SelectHandler): React.ReactElement => {
852
+ return (
853
+ <AreaChartElement
854
+ data={series}
855
+ xAxis={xAxis}
856
+ yAxis={yAxis}
857
+ curve={ChartCurve.LINEAR}
858
+ heightInPx={300}
859
+ showLegend={false}
860
+ sync={false}
861
+ syncid="real-recharts-drag-area"
862
+ onTimeRangeSelect={onTimeRangeSelect}
863
+ />
864
+ );
865
+ },
866
+ },
867
+ {
868
+ name: "bar",
869
+ render: (onTimeRangeSelect: SelectHandler): React.ReactElement => {
870
+ return (
871
+ <BarChartElement
872
+ data={series}
873
+ xAxis={xAxis}
874
+ yAxis={yAxis}
875
+ heightInPx={300}
876
+ showLegend={false}
877
+ sync={false}
878
+ syncid="real-recharts-drag-bar"
879
+ onTimeRangeSelect={onTimeRangeSelect}
880
+ />
881
+ );
882
+ },
883
+ },
884
+ ];
885
+
886
+ for (const element of elements) {
887
+ test(`a drag across the ${element.name} chart zooms exactly the minutes under the pointer`, () => {
888
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
889
+ renderChartElement(element.render(onTimeRangeSelect));
890
+
891
+ pressAt("10:12");
892
+ dragTo("10:14");
893
+ dragTo("10:15");
894
+ releaseAt("10:15");
895
+
896
+ expect(selections(onTimeRangeSelect)).toEqual([
897
+ zoomWindow("10:12", "10:16"),
898
+ ]);
899
+ });
900
+
901
+ test(`a right-to-left drag across the ${element.name} chart from its first minute zooms from the start of that minute`, () => {
902
+ const onTimeRangeSelect: MockFunction = getJestMockFunction();
903
+ renderChartElement(element.render(onTimeRangeSelect));
904
+
905
+ pressAt("10:10");
906
+ dragTo("10:08");
907
+ releaseOnThePage();
908
+
909
+ /*
910
+ * From 10:08:00, the start of the minute the first row draws: not
911
+ * 10:08:11, where the window happened to start.
912
+ */
913
+ expect(selections(onTimeRangeSelect)).toEqual([
914
+ zoomWindow("10:08", "10:11"),
915
+ ]);
916
+ });
917
+ }
918
+ });