@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.
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/KubernetesAiAgent.ts +364 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +3 -3
- package/Models/DatabaseModels/Project.ts +55 -5
- package/Models/DatabaseModels/ProxmoxResource.ts +49 -1
- package/Models/DatabaseModels/RunnerJob.ts +75 -0
- package/Models/DatabaseModels/TeamComplianceSetting.ts +143 -2
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +17 -0
- package/Server/API/AIChatAPI.ts +6 -3
- package/Server/API/AIInvestigationAPI.ts +17 -10
- package/Server/API/AutoRemediationAPI.ts +207 -25
- package/Server/API/KubernetesClusterAiAccessAPI.ts +623 -21
- package/Server/API/MicrosoftTeamsAPI.ts +93 -14
- package/Server/API/ProxmoxResourceAPI.ts +244 -14
- package/Server/Infrastructure/GlobalCache.ts +32 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.ts +99 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.ts +137 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.ts +42 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/TelemetryIngest.ts +41 -18
- package/Server/Services/AIService.ts +70 -1
- package/Server/Services/AlertService.ts +352 -11
- package/Server/Services/AlertSeverityService.ts +65 -15
- package/Server/Services/AutoRemediationRuleService.ts +1 -1
- package/Server/Services/IncidentService.ts +280 -104
- package/Server/Services/IncidentSeverityService.ts +66 -15
- package/Server/Services/KubernetesAiAgentJobService.ts +185 -0
- package/Server/Services/KubernetesAiAgentService.ts +1634 -0
- package/Server/Services/KubernetesClusterAiAccessService.ts +1118 -451
- package/Server/Services/KubernetesClusterService.ts +129 -21
- package/Server/Services/ProjectService.ts +32 -0
- package/Server/Services/ProxmoxResourceService.ts +322 -5
- package/Server/Services/RunnerJobService.ts +241 -104
- package/Server/Services/RunnerService.ts +1 -1
- package/Server/Services/ScheduledMaintenanceService.ts +737 -1
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +414 -56
- package/Server/Services/TeamComplianceSettingService.ts +1125 -9
- package/Server/Utils/AI/ClusterAccess/ClusterAccessContext.ts +67 -9
- package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +39 -10
- package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +14 -3
- package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +37 -15
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +67 -24
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +48 -5
- package/Server/Utils/AI/SRE/IncidentPostmortemRunner.ts +40 -8
- package/Server/Utils/AI/SRE/InvestigationEligibility.ts +13 -2
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +1 -1
- package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +6 -1
- package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +133 -7
- package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +58 -4
- package/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.ts +447 -0
- package/Server/Utils/Telemetry/ProxmoxNativePush.ts +903 -0
- package/Server/Utils/Telemetry/TelemetryEntity.ts +87 -27
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +684 -47
- package/Tests/App/AdminDashboard/RowActionPlacementOverrides.test.tsx +278 -0
- package/Tests/App/Dashboard/AIChatChartWidgetZoom.test.tsx +738 -0
- package/Tests/App/Dashboard/AIFeaturesSettingsPointers.test.tsx +147 -0
- package/Tests/App/Dashboard/AIInsightsKubernetesClusterPage.test.tsx +1523 -0
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +463 -3
- package/Tests/App/Dashboard/AffectedResourcesPickerDropdownPlacement.test.tsx +958 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerFocusLeave.test.tsx +595 -0
- package/Tests/App/Dashboard/AskAiAvailability.test.ts +20 -3
- package/Tests/App/Dashboard/AskAiDisabled.test.tsx +8 -3
- package/Tests/App/Dashboard/CephRateChartReload.test.tsx +1456 -0
- package/Tests/App/Dashboard/CephTimeRangeZoom.test.tsx +1229 -0
- package/Tests/App/Dashboard/ChartCardTimeRangeZoom.test.tsx +151 -0
- package/Tests/App/Dashboard/ChartCardZoomAffordances.test.tsx +257 -0
- package/Tests/App/Dashboard/ChartRefetchFrame.test.tsx +141 -0
- package/Tests/App/Dashboard/ChartZoomHarness.tsx +249 -0
- package/Tests/App/Dashboard/ChartZoomStandIn.tsx +131 -0
- package/Tests/App/Dashboard/CloudServerlessSlowLoads.test.tsx +628 -0
- package/Tests/App/Dashboard/CloudServerlessTimeRangeZoom.test.tsx +607 -0
- package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +91 -19
- package/Tests/App/Dashboard/CompanionMetricsTabZoom.test.tsx +632 -0
- package/Tests/App/Dashboard/ContainerChartZoomStandIn.tsx +195 -0
- package/Tests/App/Dashboard/ContainerHostOverviewSlowLoads.test.tsx +542 -0
- package/Tests/App/Dashboard/ContainerHostOverviewTimeRangeZoom.test.tsx +848 -0
- package/Tests/App/Dashboard/ContainerMetricsTimeRangeZoom.test.tsx +561 -0
- package/Tests/App/Dashboard/DashboardBoardWideZoomShell.test.tsx +1147 -0
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +3 -2
- package/Tests/App/Dashboard/DashboardHistogramWidgetDragCursor.test.tsx +399 -0
- package/Tests/App/Dashboard/DashboardHistogramWidgetZoom.test.tsx +985 -0
- package/Tests/App/Dashboard/DashboardHistogramWidgetZoomHint.test.tsx +803 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +1 -0
- package/Tests/App/Dashboard/DashboardSettingsPreviewZoom.test.tsx +679 -0
- package/Tests/App/Dashboard/DashboardSloAndDataSourceChartZoom.test.tsx +881 -0
- package/Tests/App/Dashboard/DashboardTraceStatusWidgets.test.tsx +878 -0
- package/Tests/App/Dashboard/DatabaseMetricChartModalTimeRangeZoom.test.tsx +442 -0
- package/Tests/App/Dashboard/DatabaseOverviewTimeRangeZoom.test.tsx +831 -0
- package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +43 -0
- package/Tests/App/Dashboard/DockerSwarmInsightsTimeRangeZoom.test.tsx +524 -0
- package/Tests/App/Dashboard/DockerSwarmRateChartRefresh.test.tsx +259 -0
- package/Tests/App/Dashboard/EdgeDetailPanelHistory.test.tsx +763 -0
- package/Tests/App/Dashboard/EdgeDetailPanelTimeRangeZoom.test.tsx +547 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsCases.tsx +565 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsKathmandu.test.tsx +73 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsKolkata.test.tsx +74 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsNewYork.test.tsx +72 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsUtc.test.tsx +72 -0
- package/Tests/App/Dashboard/EmbeddedMetricCardRefresh.test.tsx +310 -0
- package/Tests/App/Dashboard/EmbeddedMetricCardTimeRangeZoom.test.tsx +536 -0
- package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +3 -1
- package/Tests/App/Dashboard/EscalationRuleRowActions.test.tsx +660 -0
- package/Tests/App/Dashboard/EventNotes.test.tsx +2 -2
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +587 -13
- package/Tests/App/Dashboard/EventOverviewSnapshotExplorerZoom.test.tsx +1139 -0
- package/Tests/App/Dashboard/EventOverviewSnapshotZoomAcrossTabs.test.tsx +1057 -0
- package/Tests/App/Dashboard/EventOverviewTelemetrySnapshotZoom.test.tsx +757 -0
- package/Tests/App/Dashboard/ExceptionOccurrenceTrendZoom.test.tsx +675 -0
- package/Tests/App/Dashboard/ExceptionOccurrencesZoomSurvivesViewSwitch.test.tsx +405 -0
- package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +67 -3
- package/Tests/App/Dashboard/ExceptionTablesSpanStatus.test.tsx +515 -0
- package/Tests/App/Dashboard/ExplorerOwnZoomRegression.test.tsx +739 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisCases.tsx +461 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisKathmandu.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisKolkata.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisNewYork.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisUtc.test.tsx +24 -0
- package/Tests/App/Dashboard/FlowTopTalkersZoomRefetch.test.tsx +722 -0
- package/Tests/App/Dashboard/FlowViewportGuard.test.tsx +2526 -0
- package/Tests/App/Dashboard/HostPagesSlowLoads.test.tsx +872 -0
- package/Tests/App/Dashboard/HostPagesTimeRangeZoom.test.tsx +1208 -0
- package/Tests/App/Dashboard/IncidentRootCauseTimeRangeZoom.test.tsx +358 -0
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +100 -9
- package/Tests/App/Dashboard/InfrastructureMetricsTabTimeRangeZoom.test.tsx +485 -0
- package/Tests/App/Dashboard/InvestigationDrawerCompanionZoom.test.tsx +655 -0
- package/Tests/App/Dashboard/InvestigationDrawerZoom.test.tsx +830 -0
- package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +338 -2
- package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +454 -16
- package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +799 -819
- package/Tests/App/Dashboard/KubernetesClusterAiAgentOverviewCard.test.tsx +367 -0
- package/Tests/App/Dashboard/KubernetesClusterAiAgentStatus.test.ts +1202 -0
- package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +106 -0
- package/Tests/App/Dashboard/KubernetesClusterAiNavigation.test.tsx +354 -0
- package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +1884 -2054
- package/Tests/App/Dashboard/KubernetesClusterAiPageServerParity.test.ts +478 -179
- package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +50 -0
- package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +2 -1
- package/Tests/App/Dashboard/KubernetesClusterOverviewZoom.test.tsx +1217 -0
- package/Tests/App/Dashboard/KubernetesClusterPagesZoom.test.tsx +731 -0
- package/Tests/App/Dashboard/KubernetesCostsLoadRecovery.test.tsx +869 -0
- package/Tests/App/Dashboard/KubernetesCostsZoom.test.tsx +1214 -0
- package/Tests/App/Dashboard/KubernetesCostsZoomExactHours.test.tsx +692 -0
- package/Tests/App/Dashboard/KubernetesNetworkThroughputReload.test.tsx +902 -0
- package/Tests/App/Dashboard/KubernetesNetworkZoomBucketEdges.test.tsx +571 -0
- package/Tests/App/Dashboard/KubernetesOverviewZoomBucketEdges.test.tsx +697 -0
- package/Tests/App/Dashboard/KubernetesResourceMetricsTabZoom.test.tsx +633 -0
- package/Tests/App/Dashboard/LogsExplorerTimeRangeZoom.test.tsx +470 -0
- package/Tests/App/Dashboard/LogsInsightsTimeRangeZoom.test.tsx +948 -0
- package/Tests/App/Dashboard/LogsViewerPinnedWindowZoom.test.tsx +486 -0
- package/Tests/App/Dashboard/MetricChartsBucketInspectorDoubleClick.test.tsx +1001 -0
- package/Tests/App/Dashboard/MetricExplorerInvestigationAutoRefresh.test.tsx +514 -0
- package/Tests/App/Dashboard/MetricExplorerSavedViewZoomRoundTrip.test.tsx +581 -0
- package/Tests/App/Dashboard/MetricExplorerTimeRangeZoom.test.tsx +1162 -0
- package/Tests/App/Dashboard/MetricMonitorPreviewZoomLabel.test.ts +72 -0
- package/Tests/App/Dashboard/MetricRowSparklineTimeRangeZoom.test.tsx +204 -0
- package/Tests/App/Dashboard/MetricViewFirstResultLands.test.tsx +408 -0
- package/Tests/App/Dashboard/MetricViewOwnZoomResetPlacement.test.tsx +952 -0
- package/Tests/App/Dashboard/MetricViewTimeRange.test.ts +139 -0
- package/Tests/App/Dashboard/MetricViewTimeRangeZoom.test.tsx +556 -0
- package/Tests/App/Dashboard/MonitorMetricsChartWrappersZoom.test.tsx +552 -0
- package/Tests/App/Dashboard/MonitorMetricsTabsTimeRangeZoom.test.tsx +740 -0
- package/Tests/App/Dashboard/MonitorOverviewChartsTimeRangeZoom.test.tsx +735 -0
- package/Tests/App/Dashboard/MonitorStepPreviewsTimeRangeZoom.test.tsx +835 -0
- package/Tests/App/Dashboard/NetworkDeviceTimeRangeZoom.test.tsx +1115 -0
- package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +186 -17
- package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +155 -46
- package/Tests/App/Dashboard/PasskeySettings.test.tsx +87 -2
- package/Tests/App/Dashboard/ProjectAISettingsPages.test.tsx +884 -0
- package/Tests/App/Dashboard/ProxmoxNodeRemove.test.tsx +621 -0
- package/Tests/App/Dashboard/ProxmoxOverviewSlowLoads.test.tsx +584 -0
- package/Tests/App/Dashboard/ProxmoxPagesTimeRangeZoom.test.tsx +823 -0
- package/Tests/App/Dashboard/ProxmoxRateChartReload.test.tsx +1253 -0
- package/Tests/App/Dashboard/PublicDashboardBoardWideZoom.test.tsx +605 -0
- package/Tests/App/Dashboard/RealRowsLineChart.tsx +250 -0
- package/Tests/App/Dashboard/RechartsHostsPlotCursor.test.tsx +513 -0
- package/Tests/App/Dashboard/RowActionPlacementOverrides.test.tsx +865 -0
- package/Tests/App/Dashboard/RumOverviewTimeRangeZoom.test.tsx +877 -0
- package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +20 -4
- package/Tests/App/Dashboard/RunnerSupersededByAiAgentNote.test.tsx +296 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +146 -36
- package/Tests/App/Dashboard/ServiceDatabaseSlowLoads.test.tsx +1166 -0
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +1243 -104
- package/Tests/App/Dashboard/ServiceOverviewTimeRangeZoom.test.tsx +792 -0
- package/Tests/App/Dashboard/SloBudgetBurnDownZoom.test.tsx +771 -0
- package/Tests/App/Dashboard/SloBudgetBurnDownZoomAffordances.test.tsx +380 -0
- package/Tests/App/Dashboard/SloEventMetricsBarChartZoom.test.tsx +369 -0
- package/Tests/App/Dashboard/SloHistoryChartsTimeRangeZoom.test.tsx +694 -0
- package/Tests/App/Dashboard/SloHistoryChartsZoomAffordances.test.tsx +497 -0
- package/Tests/App/Dashboard/SloMetricsTimeRangeZoom.test.tsx +541 -0
- package/Tests/App/Dashboard/SlowLoadHarness.ts +123 -0
- package/Tests/App/Dashboard/SnapshotExplorerPrimaryZoom.test.tsx +1194 -0
- package/Tests/App/Dashboard/SnapshotViewerPinnedWindow.test.tsx +620 -0
- package/Tests/App/Dashboard/TelemetrySnapshotPanelTimeRangeZoom.test.tsx +765 -0
- package/Tests/App/Dashboard/TelemetrySnapshotZoom.test.tsx +516 -0
- package/Tests/App/Dashboard/TelemetrySnapshotZoomAcrossTabs.test.tsx +827 -0
- package/Tests/App/Dashboard/TimeRangeZoomPageHarness.tsx +463 -0
- package/Tests/App/Dashboard/TraceChartEditorStatusSplit.test.tsx +543 -0
- package/Tests/App/Dashboard/TraceStatusPresentation.test.tsx +967 -0
- package/Tests/App/Dashboard/TraceTimelineMinimapZoom.test.tsx +315 -0
- package/Tests/App/Dashboard/TracesAnalyticsStatusSplit.test.tsx +778 -0
- package/Tests/App/Dashboard/TracesAnalyticsViewZoom.test.tsx +349 -0
- package/Tests/App/Dashboard/TracesExplorerTimeRangeZoom.test.tsx +551 -0
- package/Tests/App/Dashboard/TracesStatusChartAndFacet.test.tsx +687 -0
- package/Tests/App/Dashboard/TracesViewerStaleResponses.test.tsx +458 -0
- package/Tests/App/Dashboard/UptimeStripsExcludedFromZoom.test.tsx +406 -0
- package/Tests/App/Dashboard/VMwareOverviewSlowLoads.test.tsx +535 -0
- package/Tests/App/Dashboard/VMwarePagesTimeRangeZoom.test.tsx +606 -0
- package/Tests/App/Dashboard/ValueWidgetSparklineStaleHover.test.tsx +1292 -0
- package/Tests/App/Dashboard/ValueWidgetSparklineZoom.test.tsx +765 -0
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +98 -0
- package/Tests/Models/DatabaseModels/KubernetesAiAgentModel.test.ts +295 -0
- package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +347 -0
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +58 -0
- package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +1 -1
- package/Tests/Server/API/AIInvestigationAPI.test.ts +123 -45
- package/Tests/Server/API/AutoRemediationApproveClusterRound.test.ts +1329 -0
- package/Tests/Server/API/AutoRemediationApproveKubectlRecheck.test.ts +25 -2
- package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -0
- package/Tests/Server/API/KubernetesClusterAiAccessAPIAgent.test.ts +903 -0
- package/Tests/Server/API/MicrosoftTeamsChatsRefreshRoute.test.ts +667 -0
- package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +294 -6
- package/Tests/Server/API/ProxmoxResourceAPIRemoveNode.test.ts +1932 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +195 -0
- package/Tests/Server/Infrastructure/Postgres/AddKubernetesAiAgentAndAiDefaultsMigration.test.ts +623 -0
- package/Tests/Server/Infrastructure/Postgres/AddKubernetesClusterAiAccessMigration.test.ts +87 -10
- package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleScopeMigration.test.ts +622 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +61 -4
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +98 -2
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +105 -2
- package/Tests/Server/Services/AIServiceBalanceBlocker.test.ts +282 -0
- package/Tests/Server/Services/AlertMonitorClearWritesNull.test.ts +409 -0
- package/Tests/Server/Services/AlertMonitorEditFeed.test.ts +474 -0
- package/Tests/Server/Services/AlertMonitorEditGuard.test.ts +610 -0
- package/Tests/Server/Services/AutoRemediationClusterRuleEngine.test.ts +2 -0
- package/Tests/Server/Services/AutoRemediationRuleCommandRunners.test.ts +2 -1
- package/Tests/Server/Services/IncidentAffectedMonitorsEdit.test.ts +1360 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +3 -1
- package/Tests/Server/Services/IncidentSeverityDeletePausesComplianceRules.test.ts +488 -0
- package/Tests/Server/Services/KubernetesAiAgentJobService.test.ts +329 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceHelpers.test.ts +618 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceLifecycle.test.ts +1444 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceRegister.test.ts +1666 -0
- package/Tests/Server/Services/KubernetesClusterAiAccessDeletedRunnerRemedy.test.ts +140 -111
- package/Tests/Server/Services/KubernetesClusterAiAccessGapNextSteps.test.ts +267 -105
- package/Tests/Server/Services/KubernetesClusterAiAccessLegacySuperseded.test.ts +440 -0
- package/Tests/Server/Services/KubernetesClusterAiAccessService.test.ts +567 -411
- package/Tests/Server/Services/KubernetesClusterAiAccessTarget.test.ts +1168 -0
- package/Tests/Server/Services/KubernetesClusterAiSettingsPermission.test.ts +410 -12
- package/Tests/Server/Services/KubernetesClusterServiceAiAccessFeed.test.ts +55 -0
- package/Tests/Server/Services/ProjectServiceNewProjectAiDefaults.test.ts +288 -0
- package/Tests/Server/Services/ProxmoxResourcePostgres.test.ts +5633 -0
- package/Tests/Server/Services/ProxmoxResourceService.test.ts +6458 -5
- package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +48 -15
- package/Tests/Server/Services/RunnerJobEnqueueKubectlAiAgent.test.ts +620 -0
- package/Tests/Server/Services/RunnerJobKubectlWriteScope.test.ts +170 -3
- package/Tests/Server/Services/RunnerJobTimeoutReason.test.ts +72 -0
- package/Tests/Server/Services/RunnerServiceAgentName.test.ts +6 -4
- package/Tests/Server/Services/ScheduledMaintenanceAttachmentEdit.test.ts +2113 -0
- package/Tests/Server/Services/ScheduledMaintenanceMonitorRelease.test.ts +972 -0
- package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +2237 -0
- package/Tests/Server/Services/TeamComplianceSettingService.test.ts +3988 -138
- package/Tests/Server/Utils/AI/ClusterAccessContext.test.ts +107 -1
- package/Tests/Server/Utils/AI/IncidentPostmortemRunner.test.ts +351 -0
- package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +2 -0
- package/Tests/Server/Utils/AI/InvestigationEligibility.test.ts +310 -0
- package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +70 -0
- package/Tests/Server/Utils/AI/KubectlJobRunnerFinishedJob.test.ts +58 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsKubectl.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsKubectlOutcome.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsLiveCluster.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsRunnerScope.test.ts +125 -1
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +252 -3
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerClusterMode.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerProjectGates.test.ts +240 -0
- package/Tests/Server/Utils/AI/RemediationKubectlCopyParity.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorUnknownRun.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +2 -0
- package/Tests/Server/Utils/Telemetry/HostAssetAttributesFromOtlp.test.ts +68 -0
- package/Tests/Server/Utils/Telemetry/InventoryMirrorPostgres.test.ts +370 -0
- package/Tests/Server/Utils/Telemetry/NetworkDeviceInventoryAttributes.test.ts +522 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +155 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.test.ts +8631 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxNativePush.test.ts +2852 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +367 -1
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +45 -3
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +25 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNames.test.ts +3119 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNamesPostgres.test.ts +1721 -0
- package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +581 -113
- package/Tests/Types/Kubernetes/KubernetesAiAgentAccessContract.test.ts +510 -0
- package/Tests/Types/Team/ComplianceRule.test.ts +1029 -0
- package/Tests/Types/Team/TeamComplianceStatus.test.ts +176 -0
- package/Tests/UI/Components/ActionButton/RowActions.test.tsx +641 -0
- package/Tests/UI/Components/ActionButton/RowActionsAccessibility.test.tsx +414 -0
- package/Tests/UI/Components/ActionButton/SplitActionButtons.test.ts +565 -0
- package/Tests/UI/Components/Charts/BarChartDragToSelect.test.tsx +386 -0
- package/Tests/UI/Components/Charts/ChartDoubleClickResetWithoutDblclick.test.tsx +1025 -0
- package/Tests/UI/Components/Charts/ChartGroupPageZoomHint.test.tsx +196 -0
- package/Tests/UI/Components/Charts/ChartPlaceholdersTakeDoubleClick.test.tsx +1861 -0
- package/Tests/UI/Components/Charts/ChartPlotClicksWhileResetArmed.test.tsx +382 -0
- package/Tests/UI/Components/Charts/ChartRangeSelection.test.tsx +704 -0
- package/Tests/UI/Components/Charts/ChartRangeSelectionDoubleClickReset.test.tsx +1481 -0
- package/Tests/UI/Components/Charts/ChartRangeSelectionRealRecharts.test.tsx +918 -0
- package/Tests/UI/Components/Charts/ChartRowBucketStart.test.ts +350 -0
- package/Tests/UI/Components/Charts/DoubleClickReset.test.tsx +996 -0
- package/Tests/UI/Components/Charts/HistogramDoubleClickResetRealRecharts.test.tsx +965 -0
- package/Tests/UI/Components/Charts/HistogramDriftThenRefetch.test.tsx +277 -0
- package/Tests/UI/Components/Charts/HistogramRangeSelectionDataChange.test.tsx +1757 -0
- package/Tests/UI/Components/Charts/HistogramRangeSelectionRealRecharts.test.tsx +560 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/ChartPageTimeRangeZoom.test.tsx +513 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.test.tsx +845 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.test.tsx +119 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHintTailwind.test.tsx +274 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.test.ts +433 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.test.tsx +863 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/ZoomDocsPromises.test.tsx +1147 -0
- package/Tests/UI/Components/DisabledButtonTooltip.test.tsx +14 -3
- package/Tests/UI/Components/EntityDropdownEscape.test.tsx +454 -0
- package/Tests/UI/Components/EntityDropdownFocusLeave.test.tsx +420 -0
- package/Tests/UI/Components/Forms/FormFieldDropdownDisabled.test.tsx +233 -0
- package/Tests/UI/Components/Input.test.tsx +80 -1
- package/Tests/UI/Components/LogsAnalyticsViewZoom.test.tsx +947 -0
- package/Tests/UI/Components/LogsHistogramDragTooltip.test.tsx +17 -5
- package/Tests/UI/Components/LogsViewerAnalyticsZoom.test.tsx +501 -0
- package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +6 -4
- package/Tests/UI/Components/ModelTable/BaseModelTablePermissionGating.test.tsx +60 -8
- package/Tests/UI/Components/ModelTable/BaseModelTableRowActions.test.tsx +476 -0
- package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +7 -5
- package/Tests/UI/Components/MoreMenuPortal.test.tsx +623 -0
- package/Tests/UI/Components/StatusPage/ResourceGridActions.test.tsx +538 -0
- package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +14 -4
- package/Tests/UI/Components/TableCellWrapping.test.tsx +3 -3
- package/Tests/UI/Components/TableRowActions.test.tsx +472 -0
- package/Tests/UI/Components/TelemetryHistogramDragTooltip.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerHistogramClickZoom.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerZoomScope.test.tsx +470 -0
- package/Tests/UI/Components/TelemetryViewer/UseViewerTimeRangeZoom.test.tsx +571 -0
- package/Tests/UI/Components/TelemetryViewer/ViewerDoubleClickResetUnderDataChange.test.tsx +928 -0
- package/Tests/UI/Components/TelemetryViewer/ViewerFollowsEnclosingZoom.test.tsx +1569 -0
- package/Tests/UI/Components/Toggle.test.tsx +66 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardRefreshNames.test.tsx +1023 -0
- package/Tests/UI/Rum/ChunkLoader.test.ts +201 -0
- package/Tests/UI/Rum/FidelityNotices.test.ts +54 -0
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +72 -0
- package/Tests/UI/Rum/ReplayFrameCapture.test.ts +1009 -9
- package/Tests/UI/Rum/ReplayRecordedAssets.test.ts +1069 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +913 -2
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +443 -8
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +439 -9
- package/Tests/UI/Rum/UserFlowTablesRowActions.test.tsx +501 -0
- package/Tests/Utils/AiRemediation/KubectlPolicyChartRbacParity.test.ts +47 -19
- package/Tests/Utils/AiRemediation/KubectlWriteScopeCallerParity.test.ts +2 -0
- package/Tests/Utils/AiRemediation/KubernetesAiAgentPolicyCopyParity.test.ts +396 -0
- package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +104 -1
- package/Types/AI/AIRunType.ts +9 -4
- package/Types/AI/InvestigationNotStartedReason.ts +6 -0
- package/Types/AutoRemediation/AiRemediationCommandPlan.ts +14 -16
- package/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.ts +28 -0
- package/Types/Dashboard/DashboardComponents/DashboardTraceChartComponent.ts +4 -2
- package/Types/Kubernetes/KubernetesClusterAiAccess.ts +263 -32
- package/Types/Kubernetes/KubernetesClusterAiAccessPermissions.ts +20 -16
- package/Types/Kubernetes/KubernetesClusterAiInsights.ts +81 -0
- package/Types/Monitor/ProxmoxAlertTemplates.ts +4 -4
- package/Types/Team/ComplianceNotificationChannel.ts +22 -0
- package/Types/Team/ComplianceRule.ts +434 -0
- package/Types/Team/ComplianceRuleType.ts +21 -0
- package/Types/Team/TeamComplianceStatus.ts +81 -0
- package/Types/Telemetry/TelemetryIngestSurface.ts +28 -0
- package/UI/Components/ActionButton/ActionButtonSchema.ts +21 -0
- package/UI/Components/ActionButton/RowActions.tsx +238 -0
- package/UI/Components/ActionButton/SplitActionButtons.ts +173 -0
- package/UI/Components/Charts/Area/AreaChart.tsx +32 -2
- package/UI/Components/Charts/Bar/BarChart.tsx +40 -3
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +37 -11
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +80 -243
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +122 -31
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +95 -244
- package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +214 -0
- package/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.ts +32 -0
- package/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.ts +599 -0
- package/UI/Components/Charts/Line/LineChart.tsx +32 -2
- package/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.tsx +70 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.tsx +226 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.tsx +73 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.ts +163 -0
- package/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.ts +215 -0
- package/UI/Components/Charts/Utils/DataPoint.ts +20 -8
- package/UI/Components/Charts/Utils/XAxis.ts +75 -0
- package/UI/Components/Charts/Utils/useHistogramRangeSelection.ts +493 -59
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +107 -11
- package/UI/Components/Forms/Fields/FormField.tsx +10 -0
- package/UI/Components/Input/Input.tsx +90 -57
- package/UI/Components/List/ListRow.tsx +8 -74
- package/UI/Components/LogsViewer/LogsViewer.tsx +40 -11
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +22 -6
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +209 -6
- package/UI/Components/LogsViewer/components/LogsHistogram.tsx +127 -84
- package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +3 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +12 -1
- package/UI/Components/MoreMenu/MoreMenu.tsx +365 -30
- package/UI/Components/MoreMenu/MoreMenuItem.tsx +70 -17
- package/UI/Components/OrderedStatesList/Item.tsx +7 -72
- package/UI/Components/StatusPage/ResourceGrid.tsx +126 -77
- package/UI/Components/Table/TableBody.tsx +8 -2
- package/UI/Components/Table/TableRow.tsx +20 -140
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +41 -10
- package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +47 -9
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +25 -6
- package/UI/Components/TelemetryViewer/types.ts +2 -0
- package/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.ts +448 -0
- package/UI/Components/Toggle/Toggle.tsx +26 -0
- package/UI/Components/Tooltip/Tooltip.tsx +8 -1
- package/UI/Styles/Theme.css +14 -2
- package/Utils/AiRemediation/CommandPolicy.ts +1 -1
- package/Utils/AiRemediation/KubectlPolicy.ts +1 -1
- package/Utils/Dashboard/DashboardTimeRangeZoom.ts +46 -2
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js +385 -0
- package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +3 -3
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +56 -5
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxResource.js +51 -1
- package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunnerJob.js +74 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +134 -3
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +6 -1
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +17 -10
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AutoRemediationAPI.js +144 -24
- package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
- package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js +436 -22
- package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +69 -13
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ProxmoxResourceAPI.js +187 -14
- package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +27 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js +84 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +34 -19
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +59 -1
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +248 -13
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AlertSeverityService.js +51 -15
- package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleService.js +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +199 -72
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSeverityService.js +51 -15
- package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesAiAgentJobService.js +158 -0
- package/build/dist/Server/Services/KubernetesAiAgentJobService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesAiAgentService.js +1145 -0
- package/build/dist/Server/Services/KubernetesAiAgentService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesClusterAiAccessService.js +842 -371
- package/build/dist/Server/Services/KubernetesClusterAiAccessService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +86 -17
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +22 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxResourceService.js +258 -3
- package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -1
- package/build/dist/Server/Services/RunnerJobService.js +178 -92
- package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
- package/build/dist/Server/Services/RunnerService.js +1 -1
- package/build/dist/Server/Services/RunnerService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +535 -3
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +316 -46
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceSettingService.js +833 -7
- package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js +52 -9
- package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +13 -9
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +7 -3
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +29 -15
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +56 -20
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +39 -5
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js +30 -3
- package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js +13 -2
- package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +1 -1
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +4 -2
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +111 -6
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +40 -4
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js +296 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js +699 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +77 -19
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +505 -42
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/AI/AIRunType.js +9 -4
- package/build/dist/Types/AI/AIRunType.js.map +1 -1
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +10 -16
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js +28 -0
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js.map +1 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +72 -16
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js +20 -16
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js +17 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js.map +1 -0
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +4 -4
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
- package/build/dist/Types/Team/ComplianceNotificationChannel.js +23 -0
- package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -0
- package/build/dist/Types/Team/ComplianceRule.js +304 -0
- package/build/dist/Types/Team/ComplianceRule.js.map +1 -0
- package/build/dist/Types/Team/ComplianceRuleType.js +21 -0
- package/build/dist/Types/Team/ComplianceRuleType.js.map +1 -1
- package/build/dist/Types/Team/TeamComplianceStatus.js +2 -0
- package/build/dist/Types/Team/TeamComplianceStatus.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +25 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
- package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js +20 -1
- package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js.map +1 -1
- package/build/dist/UI/Components/ActionButton/RowActions.js +113 -0
- package/build/dist/UI/Components/ActionButton/RowActions.js.map +1 -0
- package/build/dist/UI/Components/ActionButton/SplitActionButtons.js +71 -0
- package/build/dist/UI/Components/ActionButton/SplitActionButtons.js.map +1 -0
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +16 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +16 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +27 -5
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +61 -194
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +84 -26
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +75 -196
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +133 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js +26 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js.map +1 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js +371 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js.map +1 -0
- package/build/dist/UI/Components/Charts/Line/LineChart.js +16 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js +35 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js +107 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js +41 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js +117 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js +121 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js.map +1 -0
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -7
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/XAxis.js +70 -0
- package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js +305 -38
- package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js.map +1 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +89 -14
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +11 -2
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +69 -54
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/List/ListRow.js +4 -39
- package/build/dist/UI/Components/List/ListRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +31 -8
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +10 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +139 -21
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +30 -8
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +10 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +253 -14
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +43 -13
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
- package/build/dist/UI/Components/OrderedStatesList/Item.js +2 -38
- package/build/dist/UI/Components/OrderedStatesList/Item.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js +53 -15
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
- package/build/dist/UI/Components/Table/TableBody.js +6 -2
- package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +12 -75
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +32 -7
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +27 -9
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +11 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js +272 -0
- package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js.map +1 -0
- package/build/dist/UI/Components/Toggle/Toggle.js +14 -1
- package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/Utils/AiRemediation/CommandPolicy.js +1 -1
- package/build/dist/Utils/AiRemediation/CommandPolicy.js.map +1 -1
- package/build/dist/Utils/AiRemediation/KubectlPolicy.js +1 -1
- package/build/dist/Utils/AiRemediation/KubectlPolicy.js.map +1 -1
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +27 -1
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,996 @@
|
|
|
1
|
+
import {
|
|
2
|
+
afterEach,
|
|
3
|
+
beforeEach,
|
|
4
|
+
describe,
|
|
5
|
+
expect,
|
|
6
|
+
jest,
|
|
7
|
+
test,
|
|
8
|
+
} from "@jest/globals";
|
|
9
|
+
import {
|
|
10
|
+
RenderHookResult,
|
|
11
|
+
RenderResult,
|
|
12
|
+
act,
|
|
13
|
+
cleanup,
|
|
14
|
+
fireEvent,
|
|
15
|
+
render,
|
|
16
|
+
renderHook,
|
|
17
|
+
screen,
|
|
18
|
+
} from "@testing-library/react";
|
|
19
|
+
import React, { FunctionComponent, ReactElement } from "react";
|
|
20
|
+
import {
|
|
21
|
+
ChartPointerEvent,
|
|
22
|
+
DoubleClickReset,
|
|
23
|
+
isSecondPressOfDoubleClick,
|
|
24
|
+
useDoubleClickReset,
|
|
25
|
+
} from "../../../../UI/Components/Charts/ChartLibrary/Utils/DoubleClick";
|
|
26
|
+
import getJestMockFunction, { MockFunction } from "../../../MockType";
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
* Issue #4116. Right after a drag zooms an explorer (Traces, Logs,
|
|
30
|
+
* Metrics, ...), its charts refetch, and the reader double-clicks to undo
|
|
31
|
+
* the zoom at exactly that moment. When the new data lands during the
|
|
32
|
+
* double-click's SECOND press, recharts re-keys the node under that press
|
|
33
|
+
* (a histogram's bars or selection band, a line's path), and Chrome sends
|
|
34
|
+
* neither a click nor a `dblclick` for a press whose node left the page
|
|
35
|
+
* before its release. A chart that reset only on `dblclick` stayed zoomed,
|
|
36
|
+
* at random: "it only works once the cursor changes to a plus".
|
|
37
|
+
*
|
|
38
|
+
* useDoubleClickReset stops the reset depending on that `dblclick`. It
|
|
39
|
+
* knows the second press by the browser's own click count
|
|
40
|
+
* (MouseEvent.detail is 2 on it, whatever becomes of its node), and that
|
|
41
|
+
* press's release arms the reset for the next task. Chrome sends the
|
|
42
|
+
* release's click and `dblclick` before then, and the `dblclick` resets
|
|
43
|
+
* and stands the fallback down. Every chart shares it:
|
|
44
|
+
* useHistogramRangeSelection (the explorers' histograms) and
|
|
45
|
+
* useChartRangeSelection (the line, area and bar charts).
|
|
46
|
+
*
|
|
47
|
+
* Pinned here, at the hook:
|
|
48
|
+
* - which presses are the second of a double-click, and so the reset;
|
|
49
|
+
* - a double-click resets EXACTLY once, whether its `dblclick` arrives or
|
|
50
|
+
* not: never zero times (the bug), and never twice (a fallback that did
|
|
51
|
+
* not stand down would reset again after the page had moved on);
|
|
52
|
+
* - only the release of the reset press arms the fallback, and only once;
|
|
53
|
+
* - a release the browser counts 1 is not the reset press's own (that is
|
|
54
|
+
* counted 2, like the press) but a later, fresh click's: the press's own
|
|
55
|
+
* release never came (the window lost focus with the button down, say),
|
|
56
|
+
* and the page-wide listener a chart adds for it heard the next one. It
|
|
57
|
+
* ends the reset press and arms nothing, so that unrelated click resets
|
|
58
|
+
* nothing - then or ever;
|
|
59
|
+
* - the reset is read when it happens: the chart re-renders in between
|
|
60
|
+
* (the refetch that started all this) and must reset with the handler it
|
|
61
|
+
* has NOW, while one that stopped offering a reset, or unmounted, resets
|
|
62
|
+
* nothing.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
type ResetHandler = () => void;
|
|
66
|
+
|
|
67
|
+
// A single click, or the first press of a double-click: the browser counts it 1.
|
|
68
|
+
const FIRST_PRESS: ChartPointerEvent = { detail: 1, button: 0, clientX: 240 };
|
|
69
|
+
|
|
70
|
+
// The second press of a double-click, with the main button: counted 2.
|
|
71
|
+
const SECOND_PRESS: ChartPointerEvent = { detail: 2, button: 0, clientX: 240 };
|
|
72
|
+
|
|
73
|
+
// The release of a first press: counted 1, like its press.
|
|
74
|
+
const FIRST_RELEASE: ChartPointerEvent = { detail: 1, button: 0, clientX: 240 };
|
|
75
|
+
|
|
76
|
+
// The second press's own release: counted 2, like its press.
|
|
77
|
+
const SECOND_RELEASE: ChartPointerEvent = {
|
|
78
|
+
detail: 2,
|
|
79
|
+
button: 0,
|
|
80
|
+
clientX: 240,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
* The release of a later, fresh click somewhere else on the page, which
|
|
85
|
+
* only a chart's page-wide listener hears: the browser counts it 1.
|
|
86
|
+
*/
|
|
87
|
+
const LATER_CLICK_RELEASE: ChartPointerEvent = {
|
|
88
|
+
detail: 1,
|
|
89
|
+
button: 0,
|
|
90
|
+
clientX: 520,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
interface ResetHookProps {
|
|
94
|
+
// The reset the chart offers on this render, if any.
|
|
95
|
+
reset: ResetHandler | undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface ChartUnderTest {
|
|
99
|
+
hook: RenderHookResult<DoubleClickReset, ResetHookProps>;
|
|
100
|
+
// Re-renders the chart, now offering this reset (or none).
|
|
101
|
+
offer: (reset: ResetHandler | undefined) => void;
|
|
102
|
+
// A press on the chart; true when the hook took it as the reset press.
|
|
103
|
+
press: (event?: ChartPointerEvent | null) => boolean;
|
|
104
|
+
/*
|
|
105
|
+
* The release of a press, over the chart or heard by the page; true when
|
|
106
|
+
* it ended the reset press.
|
|
107
|
+
*/
|
|
108
|
+
release: (event?: ChartPointerEvent | null) => boolean;
|
|
109
|
+
// The browser's dblclick on the chart.
|
|
110
|
+
doubleClick: () => void;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/*
|
|
114
|
+
* The hook the way a chart drives it: every press, every release and the
|
|
115
|
+
* dblclick go through the object it returned on the chart's latest render.
|
|
116
|
+
*/
|
|
117
|
+
function renderChart(reset: ResetHandler | undefined): ChartUnderTest {
|
|
118
|
+
const hook: RenderHookResult<DoubleClickReset, ResetHookProps> = renderHook(
|
|
119
|
+
(props: ResetHookProps): DoubleClickReset => {
|
|
120
|
+
return useDoubleClickReset(props.reset);
|
|
121
|
+
},
|
|
122
|
+
{ initialProps: { reset: reset } },
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
hook: hook,
|
|
127
|
+
offer: (nextReset: ResetHandler | undefined): void => {
|
|
128
|
+
hook.rerender({ reset: nextReset });
|
|
129
|
+
},
|
|
130
|
+
press: (event?: ChartPointerEvent | null): boolean => {
|
|
131
|
+
let isResetPress: boolean = false;
|
|
132
|
+
act(() => {
|
|
133
|
+
isResetPress = hook.result.current.onPress(event);
|
|
134
|
+
});
|
|
135
|
+
return isResetPress;
|
|
136
|
+
},
|
|
137
|
+
release: (event?: ChartPointerEvent | null): boolean => {
|
|
138
|
+
let endedResetPress: boolean = false;
|
|
139
|
+
act(() => {
|
|
140
|
+
endedResetPress = hook.result.current.onRelease(event);
|
|
141
|
+
});
|
|
142
|
+
return endedResetPress;
|
|
143
|
+
},
|
|
144
|
+
doubleClick: (): void => {
|
|
145
|
+
act(() => {
|
|
146
|
+
hook.result.current.onDoubleClick();
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/*
|
|
153
|
+
* The task after the release's own. Chrome has sent the release's click
|
|
154
|
+
* and dblclick by then, when it sends them at all.
|
|
155
|
+
*/
|
|
156
|
+
function runNextTask(): void {
|
|
157
|
+
act(() => {
|
|
158
|
+
jest.advanceTimersByTime(0);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Everything still pending, however far off.
|
|
163
|
+
function runAllTimers(): void {
|
|
164
|
+
act(() => {
|
|
165
|
+
jest.runAllTimers();
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/*
|
|
170
|
+
* The microtasks after the release, where React commits: both the native
|
|
171
|
+
* queue and the one the fake timers keep (queueMicrotask, nextTick).
|
|
172
|
+
*/
|
|
173
|
+
async function runMicrotasks(): Promise<void> {
|
|
174
|
+
jest.runAllTicks();
|
|
175
|
+
for (let turn: number = 0; turn < 10; turn++) {
|
|
176
|
+
await Promise.resolve();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
beforeEach(() => {
|
|
181
|
+
jest.useFakeTimers();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
afterEach(() => {
|
|
185
|
+
cleanup();
|
|
186
|
+
jest.useRealTimers();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe("isSecondPressOfDoubleClick", () => {
|
|
190
|
+
const SECOND_PRESSES: Array<[string, ChartPointerEvent]> = [
|
|
191
|
+
["the second press of a double-click", { detail: 2, button: 0 }],
|
|
192
|
+
[
|
|
193
|
+
"a second press that does not say which button (so the main one)",
|
|
194
|
+
{ detail: 2, clientX: 240 },
|
|
195
|
+
],
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
test.each(SECOND_PRESSES)(
|
|
199
|
+
"counts %s",
|
|
200
|
+
(_name: string, event: ChartPointerEvent) => {
|
|
201
|
+
expect(isSecondPressOfDoubleClick(event)).toBe(true);
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const OTHER_PRESSES: Array<[string, ChartPointerEvent]> = [
|
|
206
|
+
["a single click", { detail: 1, button: 0 }],
|
|
207
|
+
[
|
|
208
|
+
"a click the browser counted 0 (a keyboard or assistive-technology click)",
|
|
209
|
+
{ detail: 0, button: 0 },
|
|
210
|
+
],
|
|
211
|
+
["a press that carries no count", { button: 0, clientX: 240 }],
|
|
212
|
+
["a press whose count is undefined", { detail: undefined, button: 0 }],
|
|
213
|
+
["an empty event", {}],
|
|
214
|
+
[
|
|
215
|
+
"a right-button double-click (it opens a context menu)",
|
|
216
|
+
{ detail: 2, button: 2 },
|
|
217
|
+
],
|
|
218
|
+
["a middle-button double-click", { detail: 2, button: 1 }],
|
|
219
|
+
["a back-button double-click", { detail: 2, button: 3 }],
|
|
220
|
+
["a right-button triple-click", { detail: 3, button: 2 }],
|
|
221
|
+
/*
|
|
222
|
+
* The browser sends dblclick at a count of 2 only, so the fallback
|
|
223
|
+
* stands in for it at 2 only: a triple-click's third press is a press.
|
|
224
|
+
*/
|
|
225
|
+
["the third press of a triple-click", { detail: 3, button: 0 }],
|
|
226
|
+
["the fourth press of a rapid multi-click", { detail: 4, button: 0 }],
|
|
227
|
+
];
|
|
228
|
+
|
|
229
|
+
test.each(OTHER_PRESSES)(
|
|
230
|
+
"does not count %s",
|
|
231
|
+
(_name: string, event: ChartPointerEvent) => {
|
|
232
|
+
expect(isSecondPressOfDoubleClick(event)).toBe(false);
|
|
233
|
+
},
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
test("does not count a press it is handed no event for", () => {
|
|
237
|
+
expect(isSecondPressOfDoubleClick()).toBe(false);
|
|
238
|
+
expect(isSecondPressOfDoubleClick(undefined)).toBe(false);
|
|
239
|
+
expect(isSecondPressOfDoubleClick(null)).toBe(false);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test("reads the count and the button off a real MouseEvent", () => {
|
|
243
|
+
// Getters on the event's prototype there, not own properties.
|
|
244
|
+
expect(
|
|
245
|
+
isSecondPressOfDoubleClick(
|
|
246
|
+
new MouseEvent("mousedown", { detail: 2, button: 0 }),
|
|
247
|
+
),
|
|
248
|
+
).toBe(true);
|
|
249
|
+
expect(
|
|
250
|
+
isSecondPressOfDoubleClick(
|
|
251
|
+
new MouseEvent("mousedown", { detail: 1, button: 0 }),
|
|
252
|
+
),
|
|
253
|
+
).toBe(false);
|
|
254
|
+
expect(
|
|
255
|
+
isSecondPressOfDoubleClick(
|
|
256
|
+
new MouseEvent("mousedown", { detail: 2, button: 2 }),
|
|
257
|
+
),
|
|
258
|
+
).toBe(false);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
describe("useDoubleClickReset", () => {
|
|
263
|
+
describe("on a chart that offers no reset", () => {
|
|
264
|
+
test("a second press is not the reset, its release is nothing, and a dblclick does nothing", () => {
|
|
265
|
+
const chart: ChartUnderTest = renderChart(undefined);
|
|
266
|
+
|
|
267
|
+
expect(chart.press(FIRST_PRESS)).toBe(false);
|
|
268
|
+
expect(chart.release()).toBe(false);
|
|
269
|
+
expect(chart.press(SECOND_PRESS)).toBe(false);
|
|
270
|
+
expect(chart.release()).toBe(false);
|
|
271
|
+
|
|
272
|
+
// Nothing armed: there is nothing to reset.
|
|
273
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
274
|
+
|
|
275
|
+
expect(() => {
|
|
276
|
+
chart.doubleClick();
|
|
277
|
+
}).not.toThrow();
|
|
278
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
test("a reset the chart has stopped offering is never called, by a double-click or its presses", () => {
|
|
282
|
+
const reset: MockFunction = getJestMockFunction();
|
|
283
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
284
|
+
|
|
285
|
+
// The zoom was undone some other way (the time picker, say).
|
|
286
|
+
chart.offer(undefined);
|
|
287
|
+
|
|
288
|
+
expect(chart.press(FIRST_PRESS)).toBe(false);
|
|
289
|
+
expect(chart.release()).toBe(false);
|
|
290
|
+
expect(chart.press(SECOND_PRESS)).toBe(false);
|
|
291
|
+
expect(chart.release()).toBe(false);
|
|
292
|
+
chart.doubleClick();
|
|
293
|
+
runAllTimers();
|
|
294
|
+
|
|
295
|
+
expect(reset).not.toHaveBeenCalled();
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
test("a press made while it offered none does not become the reset when one is offered before its release", () => {
|
|
299
|
+
const reset: MockFunction = getJestMockFunction();
|
|
300
|
+
const chart: ChartUnderTest = renderChart(undefined);
|
|
301
|
+
|
|
302
|
+
/*
|
|
303
|
+
* The chart already handled this press as whatever it was (the start
|
|
304
|
+
* of a selection, say), so its release cannot turn it into the reset.
|
|
305
|
+
*/
|
|
306
|
+
expect(chart.press(SECOND_PRESS)).toBe(false);
|
|
307
|
+
chart.offer(reset);
|
|
308
|
+
expect(chart.release()).toBe(false);
|
|
309
|
+
runAllTimers();
|
|
310
|
+
|
|
311
|
+
expect(reset).not.toHaveBeenCalled();
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
describe("a double-click whose dblclick arrives", () => {
|
|
316
|
+
test("resets once, at the dblclick, and the fallback its release armed stands down", () => {
|
|
317
|
+
const reset: MockFunction = getJestMockFunction();
|
|
318
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
319
|
+
|
|
320
|
+
expect(chart.press(FIRST_PRESS)).toBe(false);
|
|
321
|
+
expect(chart.release()).toBe(false);
|
|
322
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
323
|
+
expect(chart.release()).toBe(true);
|
|
324
|
+
expect(reset).not.toHaveBeenCalled();
|
|
325
|
+
|
|
326
|
+
chart.doubleClick();
|
|
327
|
+
|
|
328
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
329
|
+
|
|
330
|
+
// The fallback must not reset a second time.
|
|
331
|
+
runNextTask();
|
|
332
|
+
runAllTimers();
|
|
333
|
+
|
|
334
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
test("the fallback waits for a task, not a microtask, so the dblclick sent straight after the release still finds it armed", async () => {
|
|
338
|
+
const reset: MockFunction = getJestMockFunction();
|
|
339
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
340
|
+
|
|
341
|
+
chart.press(FIRST_PRESS);
|
|
342
|
+
chart.release();
|
|
343
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
344
|
+
expect(chart.release()).toBe(true);
|
|
345
|
+
|
|
346
|
+
/*
|
|
347
|
+
* Chrome runs the release's microtasks (React commits there) before
|
|
348
|
+
* it sends the release's click and the dblclick. A fallback run from
|
|
349
|
+
* there would reset before the dblclick, which would then reset
|
|
350
|
+
* again.
|
|
351
|
+
*/
|
|
352
|
+
await runMicrotasks();
|
|
353
|
+
|
|
354
|
+
expect(reset).not.toHaveBeenCalled();
|
|
355
|
+
|
|
356
|
+
chart.doubleClick();
|
|
357
|
+
runAllTimers();
|
|
358
|
+
|
|
359
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
test("resets once from a dblclick with no reset press before it", () => {
|
|
363
|
+
/*
|
|
364
|
+
* Its presses landed where the chart's press handlers do not run
|
|
365
|
+
* (the chart box's padding), or on a chart wired for dblclick only.
|
|
366
|
+
*/
|
|
367
|
+
const reset: MockFunction = getJestMockFunction();
|
|
368
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
369
|
+
|
|
370
|
+
chart.doubleClick();
|
|
371
|
+
|
|
372
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
373
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
374
|
+
|
|
375
|
+
runAllTimers();
|
|
376
|
+
|
|
377
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
test("presses the chart could not count are never the reset, and the dblclick still resets once", () => {
|
|
381
|
+
const reset: MockFunction = getJestMockFunction();
|
|
382
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
383
|
+
|
|
384
|
+
// A caller that hands the hook no event: dblclick is all it has.
|
|
385
|
+
expect(chart.press()).toBe(false);
|
|
386
|
+
expect(chart.release()).toBe(false);
|
|
387
|
+
expect(chart.press(null)).toBe(false);
|
|
388
|
+
expect(chart.release()).toBe(false);
|
|
389
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
390
|
+
|
|
391
|
+
chart.doubleClick();
|
|
392
|
+
runAllTimers();
|
|
393
|
+
|
|
394
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test("a dblclick resets with the reset of the chart's latest render", () => {
|
|
398
|
+
const firstReset: MockFunction = getJestMockFunction();
|
|
399
|
+
const latestReset: MockFunction = getJestMockFunction();
|
|
400
|
+
const chart: ChartUnderTest = renderChart(firstReset);
|
|
401
|
+
|
|
402
|
+
chart.offer(latestReset);
|
|
403
|
+
chart.doubleClick();
|
|
404
|
+
runAllTimers();
|
|
405
|
+
|
|
406
|
+
expect(latestReset).toHaveBeenCalledTimes(1);
|
|
407
|
+
expect(firstReset).not.toHaveBeenCalled();
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
describe("a double-click whose dblclick never arrives (issue #4116)", () => {
|
|
412
|
+
test("resets once, in the task after the second press's release", () => {
|
|
413
|
+
const reset: MockFunction = getJestMockFunction();
|
|
414
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
415
|
+
|
|
416
|
+
expect(chart.press(FIRST_PRESS)).toBe(false);
|
|
417
|
+
expect(chart.release()).toBe(false);
|
|
418
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
419
|
+
expect(chart.release()).toBe(true);
|
|
420
|
+
|
|
421
|
+
// Not during the release: the browser may yet send the dblclick.
|
|
422
|
+
expect(reset).not.toHaveBeenCalled();
|
|
423
|
+
|
|
424
|
+
runNextTask();
|
|
425
|
+
|
|
426
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
427
|
+
|
|
428
|
+
runAllTimers();
|
|
429
|
+
|
|
430
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
test("resets with the chart's newest reset when new data re-renders the chart during the second press", () => {
|
|
434
|
+
const resetBeforeRefetch: MockFunction = getJestMockFunction();
|
|
435
|
+
const resetAfterRefetch: MockFunction = getJestMockFunction();
|
|
436
|
+
const chart: ChartUnderTest = renderChart(resetBeforeRefetch);
|
|
437
|
+
|
|
438
|
+
chart.press(FIRST_PRESS);
|
|
439
|
+
chart.release();
|
|
440
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
441
|
+
|
|
442
|
+
/*
|
|
443
|
+
* The refetch lands mid-press. The histogram hands the hook a new
|
|
444
|
+
* zoom-out on every render.
|
|
445
|
+
*/
|
|
446
|
+
chart.offer(resetAfterRefetch);
|
|
447
|
+
|
|
448
|
+
expect(chart.release()).toBe(true);
|
|
449
|
+
|
|
450
|
+
runNextTask();
|
|
451
|
+
|
|
452
|
+
expect(resetAfterRefetch).toHaveBeenCalledTimes(1);
|
|
453
|
+
expect(resetBeforeRefetch).not.toHaveBeenCalled();
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
test("reads the reset when it resets: a re-render between the release and the fallback hands it the new one", () => {
|
|
457
|
+
const olderReset: MockFunction = getJestMockFunction();
|
|
458
|
+
const newerReset: MockFunction = getJestMockFunction();
|
|
459
|
+
const chart: ChartUnderTest = renderChart(olderReset);
|
|
460
|
+
|
|
461
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
462
|
+
expect(chart.release()).toBe(true);
|
|
463
|
+
|
|
464
|
+
chart.offer(newerReset);
|
|
465
|
+
runNextTask();
|
|
466
|
+
|
|
467
|
+
expect(newerReset).toHaveBeenCalledTimes(1);
|
|
468
|
+
expect(olderReset).not.toHaveBeenCalled();
|
|
469
|
+
|
|
470
|
+
runAllTimers();
|
|
471
|
+
|
|
472
|
+
expect(newerReset).toHaveBeenCalledTimes(1);
|
|
473
|
+
expect(olderReset).not.toHaveBeenCalled();
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
test("resets nothing when the chart stops offering a reset before the fallback runs", () => {
|
|
477
|
+
const reset: MockFunction = getJestMockFunction();
|
|
478
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
479
|
+
|
|
480
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
481
|
+
expect(chart.release()).toBe(true);
|
|
482
|
+
|
|
483
|
+
chart.offer(undefined);
|
|
484
|
+
runAllTimers();
|
|
485
|
+
|
|
486
|
+
expect(reset).not.toHaveBeenCalled();
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
test("resets nothing once the chart has unmounted", () => {
|
|
490
|
+
const reset: MockFunction = getJestMockFunction();
|
|
491
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
492
|
+
|
|
493
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
494
|
+
expect(chart.release()).toBe(true);
|
|
495
|
+
|
|
496
|
+
chart.hook.unmount();
|
|
497
|
+
runAllTimers();
|
|
498
|
+
|
|
499
|
+
expect(reset).not.toHaveBeenCalled();
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
test("arms one reset for a release it hears twice (the chart's own and the page's)", () => {
|
|
503
|
+
const reset: MockFunction = getJestMockFunction();
|
|
504
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
505
|
+
|
|
506
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
507
|
+
expect(chart.release()).toBe(true);
|
|
508
|
+
expect(jest.getTimerCount()).toBe(1);
|
|
509
|
+
|
|
510
|
+
expect(chart.release()).toBe(false);
|
|
511
|
+
expect(jest.getTimerCount()).toBe(1);
|
|
512
|
+
|
|
513
|
+
runAllTimers();
|
|
514
|
+
|
|
515
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
test("is ready again afterwards: a later double-click resets once more", () => {
|
|
519
|
+
const reset: MockFunction = getJestMockFunction();
|
|
520
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
521
|
+
|
|
522
|
+
// This double-click lost its dblclick: the fallback resets.
|
|
523
|
+
chart.press(FIRST_PRESS);
|
|
524
|
+
chart.release();
|
|
525
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
526
|
+
expect(chart.release()).toBe(true);
|
|
527
|
+
runNextTask();
|
|
528
|
+
|
|
529
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
530
|
+
|
|
531
|
+
// Zoomed in again, and this double-click keeps its dblclick.
|
|
532
|
+
expect(chart.press(FIRST_PRESS)).toBe(false);
|
|
533
|
+
expect(chart.release()).toBe(false);
|
|
534
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
535
|
+
expect(chart.release()).toBe(true);
|
|
536
|
+
chart.doubleClick();
|
|
537
|
+
runAllTimers();
|
|
538
|
+
|
|
539
|
+
expect(reset).toHaveBeenCalledTimes(2);
|
|
540
|
+
});
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
describe("presses that are not the reset arm nothing", () => {
|
|
544
|
+
test("a single click", () => {
|
|
545
|
+
const reset: MockFunction = getJestMockFunction();
|
|
546
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
547
|
+
|
|
548
|
+
expect(chart.press(FIRST_PRESS)).toBe(false);
|
|
549
|
+
expect(chart.release()).toBe(false);
|
|
550
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
551
|
+
|
|
552
|
+
runAllTimers();
|
|
553
|
+
|
|
554
|
+
expect(reset).not.toHaveBeenCalled();
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
test("a right-button or middle-button double-click", () => {
|
|
558
|
+
const reset: MockFunction = getJestMockFunction();
|
|
559
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
560
|
+
|
|
561
|
+
for (const button of [2, 1]) {
|
|
562
|
+
expect(chart.press({ detail: 1, button: button })).toBe(false);
|
|
563
|
+
expect(chart.release()).toBe(false);
|
|
564
|
+
expect(chart.press({ detail: 2, button: button })).toBe(false);
|
|
565
|
+
expect(chart.release()).toBe(false);
|
|
566
|
+
}
|
|
567
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
568
|
+
|
|
569
|
+
runAllTimers();
|
|
570
|
+
|
|
571
|
+
expect(reset).not.toHaveBeenCalled();
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
test("a reset press superseded by a new plain press, then a release", () => {
|
|
575
|
+
const reset: MockFunction = getJestMockFunction();
|
|
576
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
577
|
+
|
|
578
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
579
|
+
|
|
580
|
+
/*
|
|
581
|
+
* Its release never reached the hook (the window lost focus
|
|
582
|
+
* mid-press, say), and the next press is a plain click.
|
|
583
|
+
*/
|
|
584
|
+
expect(chart.press(FIRST_PRESS)).toBe(false);
|
|
585
|
+
expect(chart.release()).toBe(false);
|
|
586
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
587
|
+
|
|
588
|
+
runAllTimers();
|
|
589
|
+
|
|
590
|
+
expect(reset).not.toHaveBeenCalled();
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
test("a release with no press on the chart before it", () => {
|
|
594
|
+
const reset: MockFunction = getJestMockFunction();
|
|
595
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
596
|
+
|
|
597
|
+
// A drag that started off the chart and ended over it.
|
|
598
|
+
expect(chart.release()).toBe(false);
|
|
599
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
600
|
+
|
|
601
|
+
runAllTimers();
|
|
602
|
+
|
|
603
|
+
expect(reset).not.toHaveBeenCalled();
|
|
604
|
+
});
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
/*
|
|
608
|
+
* Any release ends the reset press: the chart's own, or one its
|
|
609
|
+
* page-wide listener hears. Only the browser's count tells the press's
|
|
610
|
+
* own release (2, like the press) from a later click's (1).
|
|
611
|
+
*/
|
|
612
|
+
describe("the release that ends the reset press", () => {
|
|
613
|
+
test("its own release, counted 2 like the press, arms the reset for the next task", () => {
|
|
614
|
+
const reset: MockFunction = getJestMockFunction();
|
|
615
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
616
|
+
|
|
617
|
+
expect(chart.press(FIRST_PRESS)).toBe(false);
|
|
618
|
+
expect(chart.release(FIRST_RELEASE)).toBe(false);
|
|
619
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
620
|
+
expect(chart.release(SECOND_RELEASE)).toBe(true);
|
|
621
|
+
expect(jest.getTimerCount()).toBe(1);
|
|
622
|
+
expect(reset).not.toHaveBeenCalled();
|
|
623
|
+
|
|
624
|
+
runNextTask();
|
|
625
|
+
|
|
626
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
627
|
+
|
|
628
|
+
runAllTimers();
|
|
629
|
+
|
|
630
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
/*
|
|
634
|
+
* Only a count of 1 says the release is someone else's. A caller that
|
|
635
|
+
* hands no event, or an event with no count of 1, gets the fallback,
|
|
636
|
+
* as every release did before the count was read.
|
|
637
|
+
*/
|
|
638
|
+
const RELEASES_THAT_ARM: Array<
|
|
639
|
+
[string, ChartPointerEvent | null | undefined]
|
|
640
|
+
> = [
|
|
641
|
+
["handed no event (a caller that has none)", undefined],
|
|
642
|
+
["handed a null event", null],
|
|
643
|
+
["the browser counts 0", { detail: 0, button: 0, clientX: 240 }],
|
|
644
|
+
["whose count is undefined", { detail: undefined, button: 0 }],
|
|
645
|
+
["that carries no count", { button: 0, clientX: 240 }],
|
|
646
|
+
];
|
|
647
|
+
|
|
648
|
+
test.each(RELEASES_THAT_ARM)(
|
|
649
|
+
"a release %s ends it and arms the reset too",
|
|
650
|
+
(_name: string, event: ChartPointerEvent | null | undefined) => {
|
|
651
|
+
const reset: MockFunction = getJestMockFunction();
|
|
652
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
653
|
+
|
|
654
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
655
|
+
expect(chart.release(event)).toBe(true);
|
|
656
|
+
expect(jest.getTimerCount()).toBe(1);
|
|
657
|
+
expect(reset).not.toHaveBeenCalled();
|
|
658
|
+
|
|
659
|
+
runNextTask();
|
|
660
|
+
|
|
661
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
662
|
+
|
|
663
|
+
// It ended the press: the same release again is nothing.
|
|
664
|
+
expect(chart.release(event)).toBe(false);
|
|
665
|
+
runAllTimers();
|
|
666
|
+
|
|
667
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
668
|
+
},
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
test("a release counted 1 - a later, fresh click's - ends it but arms nothing, and nothing after it resets", () => {
|
|
672
|
+
const reset: MockFunction = getJestMockFunction();
|
|
673
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
674
|
+
|
|
675
|
+
expect(chart.press(FIRST_PRESS)).toBe(false);
|
|
676
|
+
expect(chart.release(FIRST_RELEASE)).toBe(false);
|
|
677
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
678
|
+
|
|
679
|
+
/*
|
|
680
|
+
* The press's own release never came: the window lost focus with the
|
|
681
|
+
* button down. This one is the next click's, anywhere on the page.
|
|
682
|
+
*/
|
|
683
|
+
expect(chart.release(LATER_CLICK_RELEASE)).toBe(true);
|
|
684
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
685
|
+
|
|
686
|
+
runAllTimers();
|
|
687
|
+
|
|
688
|
+
expect(reset).not.toHaveBeenCalled();
|
|
689
|
+
|
|
690
|
+
// The reset press is over: no later release, however counted, ends it.
|
|
691
|
+
expect(chart.release(SECOND_RELEASE)).toBe(false);
|
|
692
|
+
expect(chart.release()).toBe(false);
|
|
693
|
+
expect(chart.release(LATER_CLICK_RELEASE)).toBe(false);
|
|
694
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
695
|
+
|
|
696
|
+
runAllTimers();
|
|
697
|
+
|
|
698
|
+
expect(reset).not.toHaveBeenCalled();
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
test("reads the release's count off a real MouseEvent, the kind a page-wide listener hands on", () => {
|
|
702
|
+
const reset: MockFunction = getJestMockFunction();
|
|
703
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
704
|
+
|
|
705
|
+
// Getters on the event's prototype there, not own properties.
|
|
706
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
707
|
+
expect(
|
|
708
|
+
chart.release(
|
|
709
|
+
new MouseEvent("mouseup", { detail: 1, button: 0, clientX: 520 }),
|
|
710
|
+
),
|
|
711
|
+
).toBe(true);
|
|
712
|
+
runAllTimers();
|
|
713
|
+
|
|
714
|
+
expect(reset).not.toHaveBeenCalled();
|
|
715
|
+
|
|
716
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
717
|
+
expect(
|
|
718
|
+
chart.release(
|
|
719
|
+
new MouseEvent("mouseup", { detail: 2, button: 0, clientX: 240 }),
|
|
720
|
+
),
|
|
721
|
+
).toBe(true);
|
|
722
|
+
runNextTask();
|
|
723
|
+
|
|
724
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
test("a reset press whose release never came, then a later click's release heard by the page: no reset, ever - and a double-click after that resets once", () => {
|
|
728
|
+
const reset: MockFunction = getJestMockFunction();
|
|
729
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
730
|
+
|
|
731
|
+
chart.press(FIRST_PRESS);
|
|
732
|
+
chart.release(FIRST_RELEASE);
|
|
733
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
734
|
+
|
|
735
|
+
// What the page hears of a click elsewhere, a while later.
|
|
736
|
+
expect(
|
|
737
|
+
chart.release(
|
|
738
|
+
new MouseEvent("mouseup", { detail: 1, button: 0, clientX: 520 }),
|
|
739
|
+
),
|
|
740
|
+
).toBe(true);
|
|
741
|
+
runAllTimers();
|
|
742
|
+
|
|
743
|
+
expect(reset).not.toHaveBeenCalled();
|
|
744
|
+
|
|
745
|
+
// Ready again: the next double-click resets, once.
|
|
746
|
+
expect(chart.press(FIRST_PRESS)).toBe(false);
|
|
747
|
+
expect(chart.release(FIRST_RELEASE)).toBe(false);
|
|
748
|
+
expect(chart.press(SECOND_PRESS)).toBe(true);
|
|
749
|
+
expect(chart.release(SECOND_RELEASE)).toBe(true);
|
|
750
|
+
runNextTask();
|
|
751
|
+
|
|
752
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
753
|
+
|
|
754
|
+
runAllTimers();
|
|
755
|
+
|
|
756
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
test("hands back the same object, with the same handlers, on every render", () => {
|
|
761
|
+
/*
|
|
762
|
+
* The charts build their own handlers on it (useCallback deps), and the
|
|
763
|
+
* histogram hands the hook a new zoom-out on every render: an object
|
|
764
|
+
* that followed the reset would rebuild every chart handler on every
|
|
765
|
+
* render.
|
|
766
|
+
*/
|
|
767
|
+
const reset: MockFunction = getJestMockFunction();
|
|
768
|
+
const chart: ChartUnderTest = renderChart(reset);
|
|
769
|
+
const first: DoubleClickReset = chart.hook.result.current;
|
|
770
|
+
|
|
771
|
+
const nextResets: Array<ResetHandler | undefined> = [
|
|
772
|
+
reset,
|
|
773
|
+
getJestMockFunction(),
|
|
774
|
+
undefined,
|
|
775
|
+
reset,
|
|
776
|
+
];
|
|
777
|
+
|
|
778
|
+
for (const nextReset of nextResets) {
|
|
779
|
+
chart.offer(nextReset);
|
|
780
|
+
|
|
781
|
+
expect(chart.hook.result.current).toBe(first);
|
|
782
|
+
expect(chart.hook.result.current.onPress).toBe(first.onPress);
|
|
783
|
+
expect(chart.hook.result.current.onRelease).toBe(first.onRelease);
|
|
784
|
+
expect(chart.hook.result.current.onDoubleClick).toBe(first.onDoubleClick);
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
});
|
|
788
|
+
|
|
789
|
+
interface ResettablePlotProps {
|
|
790
|
+
reset: ResetHandler | undefined;
|
|
791
|
+
/*
|
|
792
|
+
* The data on show. New data re-keys the bar, the way recharts re-keys a
|
|
793
|
+
* histogram's bars and a line's path.
|
|
794
|
+
*/
|
|
795
|
+
dataVersion: number;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/*
|
|
799
|
+
* A plot wired the way the charts wire the hook: the press and the release
|
|
800
|
+
* handlers get the React mouse event, and the dblclick handler is the
|
|
801
|
+
* hook's own. A reset press also listens for its release on the page, where
|
|
802
|
+
* a release off the plot is heard (the plot never hears it), and hands the
|
|
803
|
+
* hook the native event; whichever hears the release first ends that.
|
|
804
|
+
*/
|
|
805
|
+
const ResettablePlot: FunctionComponent<ResettablePlotProps> = (
|
|
806
|
+
props: ResettablePlotProps,
|
|
807
|
+
): ReactElement => {
|
|
808
|
+
const doubleClickReset: DoubleClickReset = useDoubleClickReset(props.reset);
|
|
809
|
+
const pageListener: React.MutableRefObject<
|
|
810
|
+
((event: ChartPointerEvent) => void) | null
|
|
811
|
+
> = React.useRef<((event: ChartPointerEvent) => void) | null>(null);
|
|
812
|
+
|
|
813
|
+
const stopListeningOnThePage: () => void = React.useCallback((): void => {
|
|
814
|
+
if (pageListener.current) {
|
|
815
|
+
window.removeEventListener("mouseup", pageListener.current);
|
|
816
|
+
pageListener.current = null;
|
|
817
|
+
}
|
|
818
|
+
}, []);
|
|
819
|
+
|
|
820
|
+
React.useEffect(() => {
|
|
821
|
+
return stopListeningOnThePage;
|
|
822
|
+
}, [stopListeningOnThePage]);
|
|
823
|
+
|
|
824
|
+
const onRelease: (event: ChartPointerEvent) => void = (
|
|
825
|
+
event: ChartPointerEvent,
|
|
826
|
+
): void => {
|
|
827
|
+
if (doubleClickReset.onRelease(event)) {
|
|
828
|
+
stopListeningOnThePage();
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
return (
|
|
833
|
+
<div
|
|
834
|
+
data-testid="plot"
|
|
835
|
+
onMouseDown={(event: React.MouseEvent<HTMLDivElement>): void => {
|
|
836
|
+
if (!doubleClickReset.onPress(event)) {
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
stopListeningOnThePage();
|
|
840
|
+
pageListener.current = onRelease;
|
|
841
|
+
window.addEventListener("mouseup", onRelease);
|
|
842
|
+
}}
|
|
843
|
+
onMouseUp={(event: React.MouseEvent<HTMLDivElement>): void => {
|
|
844
|
+
onRelease(event);
|
|
845
|
+
}}
|
|
846
|
+
onDoubleClick={doubleClickReset.onDoubleClick}
|
|
847
|
+
>
|
|
848
|
+
<span key={props.dataVersion} data-testid="bar" />
|
|
849
|
+
</div>
|
|
850
|
+
);
|
|
851
|
+
};
|
|
852
|
+
|
|
853
|
+
function bar(): HTMLElement {
|
|
854
|
+
return screen.getByTestId("bar");
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
describe("useDoubleClickReset on the mouse events React and the page deliver", () => {
|
|
858
|
+
test("a double-click that keeps its dblclick resets once, at the dblclick", () => {
|
|
859
|
+
const reset: MockFunction = getJestMockFunction();
|
|
860
|
+
render(<ResettablePlot reset={reset} dataVersion={1} />);
|
|
861
|
+
|
|
862
|
+
fireEvent.mouseDown(bar(), { detail: 1 });
|
|
863
|
+
fireEvent.mouseUp(bar(), { detail: 1 });
|
|
864
|
+
fireEvent.click(bar(), { detail: 1 });
|
|
865
|
+
fireEvent.mouseDown(bar(), { detail: 2 });
|
|
866
|
+
fireEvent.mouseUp(bar(), { detail: 2 });
|
|
867
|
+
fireEvent.click(bar(), { detail: 2 });
|
|
868
|
+
|
|
869
|
+
expect(reset).not.toHaveBeenCalled();
|
|
870
|
+
|
|
871
|
+
fireEvent.dblClick(bar(), { detail: 2 });
|
|
872
|
+
|
|
873
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
874
|
+
|
|
875
|
+
runAllTimers();
|
|
876
|
+
|
|
877
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
test("new data landing during the second press costs the click and the dblclick, and it still resets once, with the new reset", () => {
|
|
881
|
+
const resetBeforeRefetch: MockFunction = getJestMockFunction();
|
|
882
|
+
const resetAfterRefetch: MockFunction = getJestMockFunction();
|
|
883
|
+
const view: RenderResult = render(
|
|
884
|
+
<ResettablePlot reset={resetBeforeRefetch} dataVersion={1} />,
|
|
885
|
+
);
|
|
886
|
+
const pressedBar: HTMLElement = bar();
|
|
887
|
+
|
|
888
|
+
fireEvent.mouseDown(pressedBar, { detail: 1 });
|
|
889
|
+
fireEvent.mouseUp(pressedBar, { detail: 1 });
|
|
890
|
+
fireEvent.click(pressedBar, { detail: 1 });
|
|
891
|
+
fireEvent.mouseDown(pressedBar, { detail: 2 });
|
|
892
|
+
|
|
893
|
+
// The refetch lands: new bars, and a new reset with them.
|
|
894
|
+
view.rerender(<ResettablePlot reset={resetAfterRefetch} dataVersion={2} />);
|
|
895
|
+
|
|
896
|
+
expect(pressedBar.isConnected).toBe(false);
|
|
897
|
+
|
|
898
|
+
/*
|
|
899
|
+
* The release lands on the new bar, and Chrome sends no click and no
|
|
900
|
+
* dblclick: the node the press went down on has left the page.
|
|
901
|
+
*/
|
|
902
|
+
fireEvent.mouseUp(bar(), { detail: 2 });
|
|
903
|
+
|
|
904
|
+
expect(resetAfterRefetch).not.toHaveBeenCalled();
|
|
905
|
+
|
|
906
|
+
runNextTask();
|
|
907
|
+
|
|
908
|
+
expect(resetAfterRefetch).toHaveBeenCalledTimes(1);
|
|
909
|
+
expect(resetBeforeRefetch).not.toHaveBeenCalled();
|
|
910
|
+
|
|
911
|
+
runAllTimers();
|
|
912
|
+
|
|
913
|
+
expect(resetAfterRefetch).toHaveBeenCalledTimes(1);
|
|
914
|
+
});
|
|
915
|
+
|
|
916
|
+
test("a right-button double-click resets nothing", () => {
|
|
917
|
+
const reset: MockFunction = getJestMockFunction();
|
|
918
|
+
render(<ResettablePlot reset={reset} dataVersion={1} />);
|
|
919
|
+
|
|
920
|
+
// The right button gets a context menu, not a click or a dblclick.
|
|
921
|
+
fireEvent.mouseDown(bar(), { detail: 1, button: 2 });
|
|
922
|
+
fireEvent.mouseUp(bar(), { detail: 1, button: 2 });
|
|
923
|
+
fireEvent.mouseDown(bar(), { detail: 2, button: 2 });
|
|
924
|
+
fireEvent.mouseUp(bar(), { detail: 2, button: 2 });
|
|
925
|
+
runAllTimers();
|
|
926
|
+
|
|
927
|
+
expect(reset).not.toHaveBeenCalled();
|
|
928
|
+
});
|
|
929
|
+
|
|
930
|
+
test("a second press let go off the plot, which only the page hears, resets once", () => {
|
|
931
|
+
const reset: MockFunction = getJestMockFunction();
|
|
932
|
+
render(<ResettablePlot reset={reset} dataVersion={1} />);
|
|
933
|
+
|
|
934
|
+
fireEvent.mouseDown(bar(), { detail: 1 });
|
|
935
|
+
fireEvent.mouseUp(bar(), { detail: 1 });
|
|
936
|
+
fireEvent.click(bar(), { detail: 1 });
|
|
937
|
+
fireEvent.mouseDown(bar(), { detail: 2 });
|
|
938
|
+
// Let go below the plot: no click and no dblclick reach it.
|
|
939
|
+
fireEvent.mouseUp(document.body, { detail: 2 });
|
|
940
|
+
|
|
941
|
+
expect(reset).not.toHaveBeenCalled();
|
|
942
|
+
|
|
943
|
+
runNextTask();
|
|
944
|
+
|
|
945
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
946
|
+
|
|
947
|
+
runAllTimers();
|
|
948
|
+
|
|
949
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
test("a second press whose release never comes, then a click elsewhere on the page: its release, which the page hears counted 1, resets nothing - then or later", () => {
|
|
953
|
+
const reset: MockFunction = getJestMockFunction();
|
|
954
|
+
render(<ResettablePlot reset={reset} dataVersion={1} />);
|
|
955
|
+
|
|
956
|
+
fireEvent.mouseDown(bar(), { detail: 1 });
|
|
957
|
+
fireEvent.mouseUp(bar(), { detail: 1 });
|
|
958
|
+
fireEvent.click(bar(), { detail: 1 });
|
|
959
|
+
fireEvent.mouseDown(bar(), { detail: 2 });
|
|
960
|
+
|
|
961
|
+
/*
|
|
962
|
+
* Its release never comes: the window lost focus with the button down.
|
|
963
|
+
* Later the reader clicks somewhere else on the page. Only the page
|
|
964
|
+
* hears that click's release, and the browser counts it 1.
|
|
965
|
+
*/
|
|
966
|
+
fireEvent.mouseDown(document.body, { detail: 1 });
|
|
967
|
+
fireEvent.mouseUp(document.body, { detail: 1 });
|
|
968
|
+
fireEvent.click(document.body, { detail: 1 });
|
|
969
|
+
runAllTimers();
|
|
970
|
+
|
|
971
|
+
expect(reset).not.toHaveBeenCalled();
|
|
972
|
+
|
|
973
|
+
/*
|
|
974
|
+
* That release ended the second press, so no later release is its end:
|
|
975
|
+
* not one over the plot that no press on it began, even counted 2, nor
|
|
976
|
+
* one on the page.
|
|
977
|
+
*/
|
|
978
|
+
fireEvent.mouseUp(bar(), { detail: 2 });
|
|
979
|
+
fireEvent.mouseUp(document.body, { detail: 2 });
|
|
980
|
+
runAllTimers();
|
|
981
|
+
|
|
982
|
+
expect(reset).not.toHaveBeenCalled();
|
|
983
|
+
|
|
984
|
+
// A double-click made afterwards resets, once.
|
|
985
|
+
fireEvent.mouseDown(bar(), { detail: 1 });
|
|
986
|
+
fireEvent.mouseUp(bar(), { detail: 1 });
|
|
987
|
+
fireEvent.click(bar(), { detail: 1 });
|
|
988
|
+
fireEvent.mouseDown(bar(), { detail: 2 });
|
|
989
|
+
fireEvent.mouseUp(bar(), { detail: 2 });
|
|
990
|
+
fireEvent.click(bar(), { detail: 2 });
|
|
991
|
+
fireEvent.dblClick(bar(), { detail: 2 });
|
|
992
|
+
runAllTimers();
|
|
993
|
+
|
|
994
|
+
expect(reset).toHaveBeenCalledTimes(1);
|
|
995
|
+
});
|
|
996
|
+
});
|