@oneuptime/common 13.0.3 → 13.0.5
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 +4 -0
- package/Models/DatabaseModels/RumApplication.ts +1 -1
- package/Models/DatabaseModels/SecurityEventConnection.ts +457 -0
- package/Models/DatabaseModels/SecurityEventConnectionRun.ts +263 -0
- package/Models/DatabaseModels/TelemetryIngestionKey.ts +2 -2
- package/Server/API/AIInvestigationAPI.ts +484 -24
- package/Server/API/GoogleSecOpsConnectionAPI.ts +249 -8
- package/Server/API/SecurityEventConnectionAPI.ts +250 -0
- package/Server/API/TelemetryAPI.ts +402 -265
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.ts +99 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Middleware/TelemetryIngest.ts +101 -6
- package/Server/Services/ExceptionAggregationService.ts +7 -16
- package/Server/Services/GoogleSecOpsConnectionService.ts +15 -0
- package/Server/Services/Index.ts +4 -0
- package/Server/Services/InventoryItemService.ts +28 -0
- package/Server/Services/LogAggregationService.ts +17 -23
- package/Server/Services/MetricAggregationService.ts +4 -14
- package/Server/Services/SecurityEventConnectionRunService.ts +10 -0
- package/Server/Services/SecurityEventConnectionService.ts +538 -0
- package/Server/Services/TraceAggregationService.ts +77 -28
- package/Server/Types/AnalyticsDatabase/ModelPermission.ts +9 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +13 -1
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +15 -1
- package/Server/Utils/AI/SRE/InvestigationEvidence.ts +658 -0
- package/Server/Utils/AI/SRE/InvestigationReferences.ts +324 -0
- package/Server/Utils/AI/Toolbox/Index.ts +38 -0
- package/Server/Utils/AI/Toolbox/TimelineTools.ts +9 -2
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +80 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +5 -3
- package/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.ts +1108 -0
- package/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.ts +732 -0
- package/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.ts +495 -0
- package/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.ts +689 -0
- package/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.ts +767 -0
- package/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.ts +571 -0
- package/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.ts +827 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.ts +610 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.ts +549 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.ts +830 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.ts +684 -0
- package/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.ts +487 -0
- package/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.ts +778 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.ts +1002 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.ts +556 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.ts +275 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.ts +53 -0
- package/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.ts +709 -0
- package/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.ts +596 -0
- package/Server/Utils/SecurityEvent/Connectors/Types.ts +191 -0
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +353 -65
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.ts +777 -0
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +747 -148
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +48 -2
- package/Server/Utils/SecurityEvent/SecurityEventDedupe.ts +81 -0
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +741 -40
- package/Server/Utils/StartServer.ts +10 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +8 -0
- package/Server/Utils/Telemetry/KubernetesResourceAttributes.ts +108 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +174 -93
- package/Server/Utils/Telemetry/ResourceFacetPlanner.ts +251 -0
- package/Server/Utils/Telemetry/ResourceFacetResolver.ts +248 -413
- package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +668 -0
- package/Server/Utils/Telemetry/TraceContextPropagation.ts +348 -0
- package/Server/Utils/Telemetry.ts +18 -0
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +413 -0
- package/Tests/App/Dashboard/AIRootCauseFeedItem.test.tsx +285 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +242 -0
- package/Tests/App/Dashboard/AlertEpisodeViewFields.test.tsx +601 -15
- package/Tests/App/Dashboard/ChangeAlertStateAIHeader.test.tsx +835 -0
- package/Tests/App/Dashboard/CloudResourceTelemetryScope.test.ts +41 -0
- package/Tests/App/Dashboard/ConnectionTestModal.test.tsx +604 -0
- package/Tests/App/Dashboard/ConnectorTestReportView.test.tsx +738 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +153 -6
- package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +165 -0
- package/Tests/App/Dashboard/EpisodeChangeState.test.tsx +1069 -0
- package/Tests/App/Dashboard/EpisodeMembersCard.test.tsx +772 -0
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +2354 -0
- package/Tests/App/Dashboard/EventOverviewSkeleton.test.tsx +210 -0
- package/Tests/App/Dashboard/EventStatBar.test.tsx +392 -0
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +247 -0
- package/Tests/App/Dashboard/ExceptionAIAssistance.test.tsx +606 -0
- package/Tests/App/Dashboard/ExceptionBreadcrumbTimeline.test.tsx +273 -0
- package/Tests/App/Dashboard/ExceptionDetailSideMenu.test.tsx +176 -0
- package/Tests/App/Dashboard/ExceptionOverviewCards.test.tsx +366 -0
- package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +371 -0
- package/Tests/App/Dashboard/ExceptionStackFrameViewer.test.tsx +440 -0
- package/Tests/App/Dashboard/ExceptionSummary.test.tsx +381 -0
- package/Tests/App/Dashboard/ExceptionTriage.test.tsx +306 -0
- package/Tests/App/Dashboard/ExceptionsResourceFacets.test.tsx +604 -0
- package/Tests/App/Dashboard/ExceptionsViewerEntityChips.test.tsx +706 -0
- package/Tests/App/Dashboard/FeedOrdering.test.ts +32 -0
- package/Tests/App/Dashboard/GoogleSecOpsConnectionForm.test.tsx +838 -0
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +18 -0
- package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +297 -20
- package/Tests/App/Dashboard/IncidentEpisodeViewFields.test.tsx +618 -13
- package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +254 -207
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +303 -135
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +1251 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +303 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +876 -8
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +35 -0
- package/Tests/App/Dashboard/InvestigationReferenceLink.test.tsx +177 -0
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +1295 -0
- package/Tests/App/Dashboard/KubernetesImageReferenceView.test.tsx +114 -0
- package/Tests/App/Dashboard/KubernetesLogsTabChips.test.tsx +285 -0
- package/Tests/App/Dashboard/LogsEntityChipNames.test.tsx +316 -0
- package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +361 -0
- package/Tests/App/Dashboard/ProfileTableEntityNames.test.tsx +432 -0
- package/Tests/App/Dashboard/ProfileViewEntityName.test.tsx +250 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +10 -0
- package/Tests/App/Dashboard/ResourceLogsTabsBareLayout.test.tsx +700 -0
- package/Tests/App/Dashboard/ResourcePageEntityNameProps.test.tsx +803 -0
- package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +11 -1
- package/Tests/App/Dashboard/ScheduledMaintenanceChangeState.test.tsx +1026 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +436 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +1195 -0
- package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +1022 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +905 -0
- package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +247 -0
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +375 -274
- package/Tests/App/Dashboard/SessionReplayAuditTable.test.tsx +410 -0
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +774 -0
- package/Tests/App/Dashboard/TopErrorsPanelResourceNames.test.tsx +316 -0
- package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +30 -0
- package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +88 -24
- package/Tests/App/Dashboard/TraceExplorer.test.tsx +1590 -0
- package/Tests/App/Dashboard/TraceWaterfall.test.tsx +488 -0
- package/Tests/App/Dashboard/TracesAnalyticsSeriesLabels.test.tsx +367 -0
- package/Tests/App/Dashboard/TracesEntityNames.test.tsx +585 -0
- package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +613 -0
- package/Tests/App/Dashboard/UseServiceNames.test.tsx +359 -0
- package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +7 -0
- package/Tests/Models/InventoryItemNaming.test.ts +132 -16
- package/Tests/Models/SecurityDomainAccessControl.test.ts +61 -17
- package/Tests/Server/API/AIInvestigationAPI.test.ts +611 -2
- package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +1098 -0
- package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +409 -0
- package/Tests/Server/API/SecurityEventConnectionAPI.test.ts +856 -0
- package/Tests/Server/API/SessionReplayAPI.test.ts +528 -1
- package/Tests/Server/API/TelemetryFacetsAPI.test.ts +810 -0
- package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +240 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +229 -0
- package/Tests/Server/Services/InventoryItemDisplayName.test.ts +66 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
- package/Tests/Server/Services/SecurityEventConnectionService.test.ts +1233 -0
- package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +53 -0
- package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +218 -0
- package/Tests/Server/Services/TelemetryResourceFacetFilters.test.ts +155 -1
- package/Tests/Server/Services/TraceAggregationExceptionScope.test.ts +142 -0
- package/Tests/Server/Services/TraceAnalyticsResourceDisplayNames.test.ts +85 -24
- package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +33 -0
- package/Tests/Server/Utils/AI/InvestigationEvidence.test.ts +1395 -0
- package/Tests/Server/Utils/AI/InvestigationReferences.test.ts +616 -0
- package/Tests/Server/Utils/AI/TimelineTools.test.ts +119 -0
- package/Tests/Server/Utils/AI/Toolbox/AIToolbox.test.ts +151 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +65 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorExceptionScope.test.ts +224 -0
- package/Tests/Server/Utils/LoggerCore.test.ts +597 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPerSeriesFanout.test.ts +55 -2
- package/Tests/Server/Utils/Monitor/MonitorTemplateUtil.test.ts +1109 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.test.ts +1240 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.test.ts +1853 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.test.ts +1129 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.test.ts +1066 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.test.ts +1568 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.test.ts +930 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.test.ts +1409 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.test.ts +763 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.test.ts +1296 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.test.ts +1102 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.test.ts +1174 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.test.ts +1032 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.test.ts +1558 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.test.ts +3041 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.test.ts +1168 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.test.ts +906 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.test.ts +1068 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.test.ts +1004 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.test.ts +784 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +113 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +5 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +93 -13
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsHttpIntegration.test.ts +23 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +25 -3
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +22 -8
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +82 -16
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSearchDetections.test.ts +730 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsThreePassPoller.test.ts +1577 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayOriginAllowlist.test.ts +41 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +1453 -18
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +711 -0
- package/Tests/Server/Utils/Telemetry/KubernetesResourceAttributes.test.ts +162 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +460 -13
- package/Tests/Server/Utils/Telemetry/ResourceFacetPlanner.test.ts +678 -0
- package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +868 -0
- package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +525 -0
- package/Tests/Server/Utils/Telemetry/TraceContextPropagation.test.ts +420 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilCorePaths.test.ts +1014 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveRotation.test.ts +9 -6
- package/Tests/Types/Rules/RuleCriteriaFieldRegistry.test.ts +276 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +73 -0
- package/Tests/Types/Rum/SessionReplayTransportContracts.test.ts +95 -0
- package/Tests/Types/SecurityEvent/Connectors/ConnectorDiagnostics.test.ts +82 -0
- package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +314 -0
- package/Tests/Types/Telemetry/ExceptionSpanScope.test.ts +89 -0
- package/Tests/Types/Telemetry/LlmConventions.test.ts +495 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +96 -0
- package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +304 -0
- package/Tests/UI/Components/ActiveFilterChipsLockedFilters.test.tsx +357 -0
- package/Tests/UI/Components/Card.test.tsx +312 -1
- package/Tests/UI/Components/CardModelDetailHeaderLayout.test.tsx +253 -0
- package/Tests/UI/Components/CardModelDetailRefresher.test.tsx +342 -0
- package/Tests/UI/Components/Checkbox.test.tsx +79 -0
- package/Tests/UI/Components/CopyTextButton.test.tsx +142 -0
- package/Tests/UI/Components/DetailCompactStyle.test.tsx +621 -0
- package/Tests/UI/Components/ErrorBoundary.test.tsx +60 -0
- package/Tests/UI/Components/FacetSections.test.tsx +581 -0
- package/Tests/UI/Components/FacetSidebarControls.test.tsx +812 -0
- package/Tests/UI/Components/FacetVisibility.test.ts +429 -0
- package/Tests/UI/Components/LockedFilterActions.test.tsx +396 -0
- package/Tests/UI/Components/LockedFilterChip.test.tsx +651 -0
- package/Tests/UI/Components/LogsEntityNames.test.ts +1769 -0
- package/Tests/UI/Components/LogsEntityNamesComponents.test.tsx +696 -0
- package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +600 -0
- package/Tests/UI/Components/LogsViewerEntityNames.test.tsx +713 -0
- package/Tests/UI/Components/MarkdownInlineReferences.test.tsx +2079 -0
- package/Tests/UI/Components/MemberRoleAssignment.test.tsx +446 -0
- package/Tests/UI/Components/ModelDetailRefetch.test.tsx +397 -0
- package/Tests/UI/Components/ModelListRefetch.test.tsx +233 -0
- package/Tests/UI/Components/ModelPageModelChange.test.tsx +409 -0
- package/Tests/UI/Components/PaginationIntegration.test.tsx +25 -0
- package/Tests/UI/Components/ResourceFacetConfigs.test.ts +172 -0
- package/Tests/UI/Components/SavedViewsSidebarIntegration.test.tsx +32 -14
- package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +44 -1
- package/Tests/UI/Components/TelemetryActiveFilterChipsLockedFilters.test.tsx +304 -0
- package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +718 -0
- package/Tests/UI/Monitor/EvaluationLogList.test.tsx +303 -0
- package/Tests/UI/Monitor/MonitorSummarySnapshotRender.test.tsx +55 -1
- package/Tests/UI/Rum/FidelityNotices.test.ts +22 -0
- package/Tests/UI/Rum/RecordingHealthCard.test.tsx +120 -136
- package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +988 -0
- package/Tests/UI/Rum/ReplayCard.test.tsx +32 -0
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +709 -12
- package/Tests/UI/Rum/ReplayHeader.test.tsx +50 -1
- package/Tests/UI/Rum/ReplayPinControl.test.tsx +67 -10
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +41 -12
- package/Tests/UI/Rum/ReplayStage.test.tsx +663 -1
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +173 -0
- package/Tests/UI/Rum/ReplayUi.test.tsx +189 -2
- package/Tests/UI/Rum/ReplayUserSessionsMenu.test.tsx +91 -0
- package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +1 -1
- package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +585 -0
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +844 -51
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +29 -1
- package/Tests/UI/Telemetry/TelemetryDetailPanel.test.tsx +288 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +31 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +6 -0
- package/Tests/UI/Utils/Clipboard.test.ts +154 -0
- package/Tests/UI/Utils/Navigation.test.ts +24 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +2205 -0
- package/Tests/UI/Utils/Telemetry/UseTelemetryEntityNames.test.tsx +844 -0
- package/Tests/Utils/AI/InvestigationReport.test.ts +2430 -0
- package/Tests/Utils/APIOutgoingRequestTracer.test.ts +137 -0
- package/Tests/Utils/Rum/SessionReplayHealth.test.ts +884 -0
- package/Tests/Utils/Rum/SessionReplayHealthDiagnosis.test.ts +40 -0
- package/Tests/Utils/Rum/SessionReplayRecordingEnded.test.ts +619 -0
- package/Tests/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.test.ts +631 -0
- package/Tests/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.test.ts +479 -0
- package/Tests/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.test.ts +507 -0
- package/Tests/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.test.ts +686 -0
- package/Tests/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.test.ts +474 -0
- package/Tests/Utils/SecurityEvent/Connectors/OktaNormalizer.test.ts +736 -0
- package/Tests/Utils/SecurityEvent/Connectors/SplunkNormalizer.test.ts +407 -0
- package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.test.ts +129 -0
- package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +57 -1
- package/Tests/Utils/Telemetry/EntityRelationship.test.ts +36 -0
- package/Tests/Utils/Telemetry/LockedFilterSearch.test.ts +600 -0
- package/Tests/Utils/Telemetry/NetworkHost.test.ts +48 -0
- package/Tests/Utils/Telemetry/OriginAllowList.test.ts +154 -0
- package/Tests/Utils/Traces/CriticalPath.test.ts +25 -0
- package/Types/AI/AIChatTypes.ts +8 -0
- package/Types/AI/InvestigationEvidence.ts +96 -0
- package/Types/Monitor/MonitorEvaluationSummary.ts +5 -0
- package/Types/OnCallDutyPolicy/Layer.ts +12 -0
- package/Types/Permission.ts +2 -2
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
- package/Types/Rum/SessionReplay.ts +109 -0
- package/Types/Rum/SessionReplayApi.ts +31 -0
- package/Types/SecurityEvent/Connectors/ConnectorDiagnostics.ts +111 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.ts +87 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +492 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.ts +41 -0
- package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +56 -1
- package/Types/SecurityEvent/GoogleSecOpsRegion.ts +34 -0
- package/Types/Telemetry/EntityType.ts +14 -0
- package/Types/Telemetry/ExceptionSpanScope.ts +83 -0
- package/Types/Telemetry/LockedFilterDetail.ts +46 -0
- package/Types/Telemetry/ResourceEntityFacet.ts +17 -10
- package/Types/Telemetry/ResourceFacetCatalog.ts +171 -0
- package/UI/Components/Card/Card.tsx +118 -83
- package/UI/Components/Checkbox/Checkbox.tsx +8 -5
- package/UI/Components/CopyTextButton/CopyTextButton.tsx +7 -1
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +4 -1
- package/UI/Components/Detail/Detail.tsx +137 -22
- package/UI/Components/ErrorBoundary.tsx +38 -0
- package/UI/Components/LogsViewer/LogsEntityNames.ts +912 -0
- package/UI/Components/LogsViewer/LogsViewer.tsx +156 -77
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +28 -11
- package/UI/Components/LogsViewer/components/FacetSection.tsx +66 -79
- package/UI/Components/LogsViewer/components/FacetValueRow.tsx +17 -2
- package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +45 -5
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +100 -19
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +156 -39
- package/UI/Components/LogsViewer/components/LogsTable.tsx +30 -8
- package/UI/Components/LogsViewer/types.ts +6 -0
- package/UI/Components/Markdown.tsx/InlineReferences.tsx +628 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +385 -312
- package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +50 -22
- package/UI/Components/ModelDetail/CardModelDetail.tsx +15 -0
- package/UI/Components/ModelDetail/ModelDetail.tsx +64 -19
- package/UI/Components/ModelList/ModelList.tsx +33 -8
- package/UI/Components/Page/ModelPage.tsx +119 -54
- package/UI/Components/Table/Table.tsx +8 -0
- package/UI/Components/Table/TableRow.tsx +13 -5
- package/UI/Components/TelemetryViewer/FacetVisibility.ts +229 -0
- package/UI/Components/TelemetryViewer/ResourceFacetConfigs.ts +46 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +11 -0
- package/UI/Components/TelemetryViewer/components/FacetSearchInput.tsx +79 -0
- package/UI/Components/TelemetryViewer/components/FacetSectionHeader.tsx +69 -0
- package/UI/Components/TelemetryViewer/components/FacetShowMoreButton.tsx +36 -0
- package/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.tsx +88 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterActions.tsx +205 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +496 -0
- package/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.tsx +30 -10
- package/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.tsx +203 -10
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSection.tsx +60 -73
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +94 -7
- package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +17 -2
- package/UI/Components/TelemetryViewer/types.ts +19 -0
- package/UI/Components/TelemetryViewer/useFacetSearchExemptions.ts +158 -0
- package/UI/Components/TelemetryViewer/useFacetSectionSearch.ts +102 -0
- package/UI/Utils/Clipboard.ts +68 -2
- package/UI/Utils/Navigation.ts +17 -2
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +620 -0
- package/UI/Utils/Telemetry/UseTelemetryEntityNames.ts +151 -0
- package/Utils/AI/InvestigationReport.ts +1789 -0
- package/Utils/API.ts +90 -1
- package/Utils/Rum/SessionReplayHealth.ts +11 -0
- package/Utils/Rum/SessionReplayRecordingEnded.ts +134 -0
- package/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.ts +427 -0
- package/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.ts +197 -0
- package/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.ts +464 -0
- package/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.ts +567 -0
- package/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.ts +299 -0
- package/Utils/SecurityEvent/Connectors/OktaNormalizer.ts +467 -0
- package/Utils/SecurityEvent/Connectors/SplunkNormalizer.ts +439 -0
- package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +124 -12
- package/Utils/Telemetry/CrossSignalScope.ts +22 -8
- package/Utils/Telemetry/EntityRelationship.ts +8 -0
- package/Utils/Telemetry/LockedFilterSearch.ts +412 -0
- package/Utils/Telemetry/NetworkHost.ts +43 -0
- package/Utils/Telemetry/OriginAllowList.ts +139 -4
- package/Utils/Traces/CriticalPath.ts +10 -4
- package/build/dist/Models/DatabaseModels/Index.js +4 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/SecurityEventConnection.js +490 -0
- package/build/dist/Models/DatabaseModels/SecurityEventConnection.js.map +1 -0
- package/build/dist/Models/DatabaseModels/SecurityEventConnectionRun.js +287 -0
- package/build/dist/Models/DatabaseModels/SecurityEventConnectionRun.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js +2 -2
- package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +336 -27
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +182 -7
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +1 -1
- package/build/dist/Server/API/SecurityEventConnectionAPI.js +171 -0
- package/build/dist/Server/API/SecurityEventConnectionAPI.js.map +1 -0
- package/build/dist/Server/API/TelemetryAPI.js +248 -170
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +57 -4
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/ExceptionAggregationService.js +7 -16
- package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +8 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +4 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +22 -0
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +8 -17
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +4 -14
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/SecurityEventConnectionRunService.js +9 -0
- package/build/dist/Server/Services/SecurityEventConnectionRunService.js.map +1 -0
- package/build/dist/Server/Services/SecurityEventConnectionService.js +356 -0
- package/build/dist/Server/Services/SecurityEventConnectionService.js.map +1 -0
- package/build/dist/Server/Services/TraceAggregationService.js +51 -25
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +3 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +14 -7
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationEvidence.js +468 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationEvidence.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationReferences.js +230 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationReferences.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +32 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js +6 -2
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +59 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +5 -3
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.js +752 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.js +493 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js +352 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.js +405 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.js +466 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.js +344 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.js +511 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.js +406 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.js +336 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.js +474 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.js +417 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.js +314 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.js +494 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js +719 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js +404 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js +209 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js +40 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.js +494 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.js +379 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js +27 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +234 -61
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js +537 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +572 -115
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +35 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js +52 -0
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +521 -32
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +10 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +8 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/KubernetesResourceAttributes.js +80 -0
- package/build/dist/Server/Utils/Telemetry/KubernetesResourceAttributes.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +122 -67
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceFacetPlanner.js +146 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetPlanner.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +174 -248
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +492 -0
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TraceContextPropagation.js +259 -0
- package/build/dist/Server/Utils/Telemetry/TraceContextPropagation.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry.js +11 -5
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Types/AI/InvestigationEvidence.js +2 -0
- package/build/dist/Types/AI/InvestigationEvidence.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +11 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/Types/Permission.js +2 -2
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +9 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplay.js +95 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js +18 -0
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js +2 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +374 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js +35 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js.map +1 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsRegion.js +35 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsRegion.js.map +1 -0
- package/build/dist/Types/Telemetry/EntityType.js +14 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ExceptionSpanScope.js +59 -0
- package/build/dist/Types/Telemetry/ExceptionSpanScope.js.map +1 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js +16 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js.map +1 -0
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js +16 -10
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js.map +1 -1
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +119 -0
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -0
- package/build/dist/UI/Components/Card/Card.js +34 -17
- package/build/dist/UI/Components/Card/Card.js.map +1 -1
- package/build/dist/UI/Components/Checkbox/Checkbox.js +6 -4
- package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/Detail/Detail.js +63 -13
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +34 -0
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsEntityNames.js +535 -0
- package/build/dist/UI/Components/LogsViewer/LogsEntityNames.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +117 -57
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +5 -7
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetSection.js +31 -44
- package/build/dist/UI/Components/LogsViewer/components/FacetSection.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +17 -3
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +19 -3
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +64 -18
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +100 -41
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +13 -5
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/InlineReferences.js +403 -0
- package/build/dist/UI/Components/Markdown.tsx/InlineReferences.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +197 -179
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +30 -21
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +12 -0
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js +46 -12
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelList/ModelList.js +26 -7
- package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
- package/build/dist/UI/Components/Page/ModelPage.js +62 -34
- package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +3 -1
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +8 -1
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +111 -0
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/ResourceFacetConfigs.js +22 -0
- package/build/dist/UI/Components/TelemetryViewer/ResourceFacetConfigs.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSearchInput.js +36 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSearchInput.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSectionHeader.js +21 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSectionHeader.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetShowMoreButton.js +14 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetShowMoreButton.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.js +27 -0
- package/build/dist/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js +88 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +228 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js +6 -6
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js +111 -12
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSection.js +27 -40
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSection.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +70 -10
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +17 -3
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/types.js +0 -4
- package/build/dist/UI/Components/TelemetryViewer/types.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/useFacetSearchExemptions.js +70 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSearchExemptions.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSectionSearch.js +52 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSectionSearch.js.map +1 -0
- package/build/dist/UI/Utils/Clipboard.js +59 -2
- package/build/dist/UI/Utils/Clipboard.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +11 -2
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +471 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -0
- package/build/dist/UI/Utils/Telemetry/UseTelemetryEntityNames.js +113 -0
- package/build/dist/UI/Utils/Telemetry/UseTelemetryEntityNames.js.map +1 -0
- package/build/dist/Utils/AI/InvestigationReport.js +1241 -0
- package/build/dist/Utils/AI/InvestigationReport.js.map +1 -0
- package/build/dist/Utils/API.js +25 -0
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Rum/SessionReplayHealth.js +10 -0
- package/build/dist/Utils/Rum/SessionReplayHealth.js.map +1 -1
- package/build/dist/Utils/Rum/SessionReplayRecordingEnded.js +54 -0
- package/build/dist/Utils/Rum/SessionReplayRecordingEnded.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.js +311 -0
- package/build/dist/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.js +150 -0
- package/build/dist/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.js +328 -0
- package/build/dist/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.js +405 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.js +212 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/OktaNormalizer.js +351 -0
- package/build/dist/Utils/SecurityEvent/Connectors/OktaNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/SplunkNormalizer.js +348 -0
- package/build/dist/Utils/SecurityEvent/Connectors/SplunkNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +103 -10
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +16 -5
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityRelationship.js +7 -0
- package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js +277 -0
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js.map +1 -0
- package/build/dist/Utils/Telemetry/NetworkHost.js +39 -0
- package/build/dist/Utils/Telemetry/NetworkHost.js.map +1 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js +105 -4
- package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -1
- package/build/dist/Utils/Traces/CriticalPath.js +9 -4
- package/build/dist/Utils/Traces/CriticalPath.js.map +1 -1
- package/package.json +1 -1
- package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +0 -600
- package/UI/Components/GanttChart/Bar/BarLabel.tsx +0 -17
- package/UI/Components/GanttChart/Bar/Index.tsx +0 -149
- package/UI/Components/GanttChart/ChartContainer.tsx +0 -50
- package/UI/Components/GanttChart/Index.tsx +0 -90
- package/UI/Components/GanttChart/Row/Index.tsx +0 -22
- package/UI/Components/GanttChart/Row/Row.tsx +0 -231
- package/UI/Components/GanttChart/Row/RowLabel.tsx +0 -30
- package/UI/Components/GanttChart/Rows.tsx +0 -59
- package/UI/Components/GanttChart/Timeline/Index.tsx +0 -46
- package/UI/Components/GanttChart/Timeline/TimelineInterval.tsx +0 -33
- package/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.tsx +0 -43
- package/build/dist/UI/Components/GanttChart/Bar/BarLabel.js +0 -8
- package/build/dist/UI/Components/GanttChart/Bar/BarLabel.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Bar/Index.js +0 -77
- package/build/dist/UI/Components/GanttChart/Bar/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/ChartContainer.js +0 -33
- package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Index.js +0 -39
- package/build/dist/UI/Components/GanttChart/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/Index.js +0 -7
- package/build/dist/UI/Components/GanttChart/Row/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/Row.js +0 -106
- package/build/dist/UI/Components/GanttChart/Row/Row.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/RowLabel.js +0 -10
- package/build/dist/UI/Components/GanttChart/Row/RowLabel.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Rows.js +0 -19
- package/build/dist/UI/Components/GanttChart/Rows.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/Index.js +0 -16
- package/build/dist/UI/Components/GanttChart/Timeline/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineInterval.js +0 -13
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineInterval.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.js +0 -13
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.js.map +0 -1
|
@@ -7,7 +7,15 @@ import {
|
|
|
7
7
|
jest,
|
|
8
8
|
test,
|
|
9
9
|
} from "@jest/globals";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
act,
|
|
12
|
+
cleanup,
|
|
13
|
+
fireEvent,
|
|
14
|
+
render,
|
|
15
|
+
screen,
|
|
16
|
+
waitFor,
|
|
17
|
+
within,
|
|
18
|
+
} from "@testing-library/react";
|
|
11
19
|
import React from "react";
|
|
12
20
|
import { Location } from "react-router-dom";
|
|
13
21
|
import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
@@ -20,7 +28,7 @@ import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
|
20
28
|
* getElement threw BadDataException("Episode Severity not found") from inside
|
|
21
29
|
* Detail's own render, so the whole route was replaced by the app level
|
|
22
30
|
* "Something went wrong" boundary. The only recovery was deleting the episode,
|
|
23
|
-
* which detached every member
|
|
31
|
+
* which detached every member alert.
|
|
24
32
|
*
|
|
25
33
|
* These tests drive the real page against a fake server and assert what a
|
|
26
34
|
* person actually sees: the Episode Severity row, holding a placeholder.
|
|
@@ -33,16 +41,30 @@ import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
|
33
41
|
* guard must NOT be what makes these pass: every case asserts the page never
|
|
34
42
|
* logged "threw and was ignored", which is how a regression at the page level
|
|
35
43
|
* stays visible instead of being quietly absorbed by the framework.
|
|
44
|
+
*
|
|
45
|
+
* The overview itself was later redesigned (header, stat bar, member list,
|
|
46
|
+
* compact details column), so the last describe blocks pin that layout's
|
|
47
|
+
* behaviour against the same fake server.
|
|
36
48
|
*/
|
|
37
49
|
|
|
38
50
|
const EPISODE_ID: string = "11111111-1111-4111-8111-111111111111";
|
|
39
51
|
const PROJECT_ID: string = "22222222-2222-4222-8222-222222222222";
|
|
52
|
+
const ACK_STATE_ID: string = "66666666-6666-4666-8666-666666666666";
|
|
53
|
+
const RESOLVED_STATE_ID: string = "77777777-7777-4777-8777-777777777777";
|
|
40
54
|
|
|
41
55
|
const getItemMock: MockFunction = getJestMockFunction();
|
|
42
56
|
const getListMock: MockFunction = getJestMockFunction();
|
|
43
57
|
const getCommonHeadersMock: MockFunction = getJestMockFunction();
|
|
44
58
|
const loggerErrorMock: MockFunction = getJestMockFunction();
|
|
45
59
|
|
|
60
|
+
// The last props the stubbed header was rendered with.
|
|
61
|
+
const changeStateProps: { current: Record<string, any> | null } = {
|
|
62
|
+
current: null,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Every set of props the stubbed header was rendered with, in order.
|
|
66
|
+
const changeStateHistory: Array<Record<string, any>> = [];
|
|
67
|
+
|
|
46
68
|
/*
|
|
47
69
|
* The arrow wrappers are load bearing: jest.mock is hoisted above the compiled
|
|
48
70
|
* requires, so the mock consts above are still unassigned when the factory
|
|
@@ -88,14 +110,17 @@ jest.mock("../../../UI/Utils/Logger", () => {
|
|
|
88
110
|
/*
|
|
89
111
|
* The page's two heavy children each drive their own API traffic and neither
|
|
90
112
|
* renders a detail field. Stubbing them keeps this suite pointed at the
|
|
91
|
-
* Episode Details card, which is where #3374 lives.
|
|
113
|
+
* Episode Details card, which is where #3374 lives. The header stub records
|
|
114
|
+
* its props so the layout tests can drive a state change.
|
|
92
115
|
*/
|
|
93
116
|
jest.mock(
|
|
94
117
|
"../../../../App/FeatureSet/Dashboard/src/Components/AlertEpisode/ChangeState",
|
|
95
118
|
() => {
|
|
96
119
|
return {
|
|
97
120
|
__esModule: true,
|
|
98
|
-
default: () => {
|
|
121
|
+
default: (props: Record<string, any>) => {
|
|
122
|
+
changeStateProps.current = props;
|
|
123
|
+
changeStateHistory.push(props);
|
|
99
124
|
return null;
|
|
100
125
|
},
|
|
101
126
|
};
|
|
@@ -116,10 +141,13 @@ jest.mock(
|
|
|
116
141
|
|
|
117
142
|
import AlertEpisodeView from "../../../../App/FeatureSet/Dashboard/src/Pages/Alerts/EpisodeView/Index";
|
|
118
143
|
import PageComponentProps from "../../../../App/FeatureSet/Dashboard/src/Pages/PageComponentProps";
|
|
144
|
+
import Alert from "../../../Models/DatabaseModels/Alert";
|
|
119
145
|
import AlertEpisode from "../../../Models/DatabaseModels/AlertEpisode";
|
|
146
|
+
import AlertEpisodeStateTimeline from "../../../Models/DatabaseModels/AlertEpisodeStateTimeline";
|
|
120
147
|
import AlertSeverity from "../../../Models/DatabaseModels/AlertSeverity";
|
|
121
148
|
import AlertState from "../../../Models/DatabaseModels/AlertState";
|
|
122
149
|
import Route from "../../../Types/API/Route";
|
|
150
|
+
import SortOrder from "../../../Types/BaseDatabase/SortOrder";
|
|
123
151
|
import Color from "../../../Types/Color";
|
|
124
152
|
import ObjectID from "../../../Types/ObjectID";
|
|
125
153
|
import Permission from "../../../Types/Permission";
|
|
@@ -214,6 +242,22 @@ const buildEpisode: BuildEpisodeFunction = (
|
|
|
214
242
|
return episode;
|
|
215
243
|
};
|
|
216
244
|
|
|
245
|
+
type EmptyListFunction = () => {
|
|
246
|
+
data: Array<unknown>;
|
|
247
|
+
count: number;
|
|
248
|
+
skip: number;
|
|
249
|
+
limit: number;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const emptyList: EmptyListFunction = () => {
|
|
253
|
+
return {
|
|
254
|
+
data: [],
|
|
255
|
+
count: 0,
|
|
256
|
+
skip: 0,
|
|
257
|
+
limit: 0,
|
|
258
|
+
};
|
|
259
|
+
};
|
|
260
|
+
|
|
217
261
|
type RenderPageFunction = (spec: EpisodeSpec) => Promise<void>;
|
|
218
262
|
|
|
219
263
|
const renderPage: RenderPageFunction = async (
|
|
@@ -232,6 +276,7 @@ const renderPage: RenderPageFunction = async (
|
|
|
232
276
|
* Detail renders each field as <container><FieldLabel/><value/></container>,
|
|
233
277
|
* and FieldLabel's root is the only div.space-y-1 in that subtree. Walking up
|
|
234
278
|
* from the label and taking the sibling is what a person reading the row does.
|
|
279
|
+
* The compact style the overview uses keeps exactly that shape.
|
|
235
280
|
*/
|
|
236
281
|
type FieldValueFunction = (title: string) => string;
|
|
237
282
|
|
|
@@ -270,6 +315,16 @@ const pillFor: PillForFunction = (title: string): HTMLElement => {
|
|
|
270
315
|
return pill;
|
|
271
316
|
};
|
|
272
317
|
|
|
318
|
+
// A stat bar cell: label span -> label row -> cell; the value is the 2nd child.
|
|
319
|
+
type StatValueFunction = (label: string) => string;
|
|
320
|
+
|
|
321
|
+
const statValue: StatValueFunction = (label: string): string => {
|
|
322
|
+
const cell: HTMLElement | null | undefined =
|
|
323
|
+
screen.getByText(label).parentElement?.parentElement;
|
|
324
|
+
|
|
325
|
+
return (cell?.children[1]?.textContent || "").trim();
|
|
326
|
+
};
|
|
327
|
+
|
|
273
328
|
type ExpectNoCrashFunction = () => void;
|
|
274
329
|
|
|
275
330
|
/*
|
|
@@ -291,18 +346,25 @@ const expectNoCrash: ExpectNoCrashFunction = (): void => {
|
|
|
291
346
|
expect(swallowed).toEqual([]);
|
|
292
347
|
};
|
|
293
348
|
|
|
349
|
+
type CallsForModelFunction = (modelType: unknown) => Array<Array<any>>;
|
|
350
|
+
|
|
351
|
+
const listCallsFor: CallsForModelFunction = (
|
|
352
|
+
modelType: unknown,
|
|
353
|
+
): Array<Array<any>> => {
|
|
354
|
+
return getListMock.mock.calls.filter((call: Array<any>): boolean => {
|
|
355
|
+
return call[0]?.modelType === modelType;
|
|
356
|
+
});
|
|
357
|
+
};
|
|
358
|
+
|
|
294
359
|
beforeEach((): void => {
|
|
295
360
|
getItemMock.mockReset();
|
|
296
361
|
getListMock.mockReset();
|
|
297
362
|
getCommonHeadersMock.mockReset();
|
|
298
363
|
loggerErrorMock.mockReset();
|
|
364
|
+
changeStateProps.current = null;
|
|
365
|
+
changeStateHistory.length = 0;
|
|
299
366
|
|
|
300
|
-
getListMock.mockResolvedValue(
|
|
301
|
-
data: [],
|
|
302
|
-
count: 0,
|
|
303
|
-
skip: 0,
|
|
304
|
-
limit: 0,
|
|
305
|
-
} as never);
|
|
367
|
+
getListMock.mockResolvedValue(emptyList() as never);
|
|
306
368
|
getCommonHeadersMock.mockReturnValue({} as never);
|
|
307
369
|
|
|
308
370
|
const path: string = `/dashboard/${PROJECT_ID}/alerts/episodes/${EPISODE_ID}`;
|
|
@@ -357,14 +419,13 @@ describe("Alert Episode detail page: severity (issue #3374)", () => {
|
|
|
357
419
|
test("still renders the rest of the episode when severity is missing", async () => {
|
|
358
420
|
await renderPage({ state: buildState("Created", new Color("#4b5563")) });
|
|
359
421
|
|
|
360
|
-
expect(screen.getByText("Episode Title")).toBeInTheDocument();
|
|
361
|
-
expect(fieldValue("Episode Title")).toEqual("episode without severity");
|
|
362
422
|
expect(fieldValue("Episode Number")).toContain("#7");
|
|
363
423
|
expect(fieldValue("Alert Count")).toEqual("0");
|
|
364
|
-
// An episode with no grouping rule is a manual one, not a crash.
|
|
365
|
-
expect(fieldValue("Grouping Rule")).toEqual("Manual Episode");
|
|
366
424
|
// No createdByUser on an API-created episode.
|
|
367
425
|
expect(fieldValue("Created By")).toEqual("System");
|
|
426
|
+
// An episode with no grouping rule is a manual one, not a crash.
|
|
427
|
+
expect(fieldValue("Grouping Rule")).toEqual("Manual Episode");
|
|
428
|
+
expect(fieldValue("Episode ID")).toContain(EPISODE_ID);
|
|
368
429
|
expectNoCrash();
|
|
369
430
|
});
|
|
370
431
|
|
|
@@ -459,7 +520,532 @@ describe("Alert Episode detail page: both relations missing", () => {
|
|
|
459
520
|
|
|
460
521
|
expect(fieldValue("Episode Severity")).toEqual("-");
|
|
461
522
|
expect(fieldValue("Current State")).toEqual("-");
|
|
462
|
-
expect(fieldValue("Episode
|
|
523
|
+
expect(fieldValue("Episode Number")).toContain("#7");
|
|
524
|
+
expectNoCrash();
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
describe("Alert Episode overview: details column", () => {
|
|
529
|
+
test("uses the compact single-column style with the episode ID last", async () => {
|
|
530
|
+
await renderPage({ state: buildState("Created", new Color("#4b5563")) });
|
|
531
|
+
|
|
532
|
+
const numberRow: HTMLElement | null | undefined = screen
|
|
533
|
+
.getByText("Episode Number")
|
|
534
|
+
.closest("div.space-y-1")?.parentElement;
|
|
535
|
+
const grid: HTMLElement | null | undefined = numberRow?.parentElement;
|
|
536
|
+
|
|
537
|
+
expect(grid).toHaveClass("grid", "grid-cols-1", "divide-y");
|
|
538
|
+
expect(grid).toHaveClass("sm:grid-cols-1");
|
|
539
|
+
expect(numberRow).toHaveClass("py-3");
|
|
540
|
+
|
|
541
|
+
const rowTitles: Array<string> = Array.from(grid!.children).map(
|
|
542
|
+
(row: Element): string => {
|
|
543
|
+
return (row.querySelector("label")?.textContent || "").trim();
|
|
544
|
+
},
|
|
545
|
+
);
|
|
546
|
+
|
|
547
|
+
expect(rowTitles).toEqual([
|
|
548
|
+
"Episode Number",
|
|
549
|
+
"Current State",
|
|
550
|
+
"Episode Severity",
|
|
551
|
+
"Alert Count",
|
|
552
|
+
"Grouping Rule",
|
|
553
|
+
"Created By",
|
|
554
|
+
"On-Call Duty Policies",
|
|
555
|
+
"Created At",
|
|
556
|
+
"Labels",
|
|
557
|
+
"Episode ID",
|
|
558
|
+
]);
|
|
559
|
+
expectNoCrash();
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
test("no longer repeats the title the header already shows", async () => {
|
|
563
|
+
await renderPage({ state: buildState("Created", new Color("#4b5563")) });
|
|
564
|
+
|
|
565
|
+
expect(screen.queryByText("Episode Title")).toBeNull();
|
|
566
|
+
expect(screen.queryByText("Last Alert Added At")).toBeNull();
|
|
567
|
+
// The number is plain text now, not a hand-rolled SVG chip.
|
|
568
|
+
const numberRow: HTMLElement | null | undefined = screen
|
|
569
|
+
.getByText("Episode Number")
|
|
570
|
+
.closest("div.space-y-1")?.parentElement;
|
|
571
|
+
|
|
572
|
+
expect(numberRow?.querySelector("svg")).toBeNull();
|
|
573
|
+
});
|
|
574
|
+
/*
|
|
575
|
+
* The details card sits in a ~300px column. Its old side-by-side header put
|
|
576
|
+
* "Edit Alert Episode" beside the title and squeezed the title and description
|
|
577
|
+
* into a column a word or two wide.
|
|
578
|
+
*/
|
|
579
|
+
test("stacks the details card header and keeps a short, gated Edit button", async () => {
|
|
580
|
+
await renderPage({ state: buildState("Created", new Color("#4b5563")) });
|
|
581
|
+
|
|
582
|
+
const header: HTMLElement = await waitFor(() => {
|
|
583
|
+
return screen.getByTestId("card-header");
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
expect(header).toHaveAttribute("data-header-layout", "stacked");
|
|
587
|
+
expect(within(header).getByText("Episode Details")).toBeInTheDocument();
|
|
588
|
+
expect(
|
|
589
|
+
within(header).getByText("Key facts about this episode."),
|
|
590
|
+
).toBeInTheDocument();
|
|
591
|
+
|
|
592
|
+
const actions: HTMLElement = await waitFor(() => {
|
|
593
|
+
return screen.getByTestId("card-header-actions");
|
|
594
|
+
});
|
|
595
|
+
const edit: HTMLElement = within(actions).getByRole("button", {
|
|
596
|
+
name: "Edit",
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
expect(edit).not.toBeDisabled();
|
|
600
|
+
expect(screen.queryByText("Edit Alert Episode")).toBeNull();
|
|
601
|
+
expect(
|
|
602
|
+
screen.queryByText("Here are more details for this episode."),
|
|
603
|
+
).toBeNull();
|
|
604
|
+
expectNoCrash();
|
|
605
|
+
});
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
describe("Alert Episode overview: loading and layout", () => {
|
|
609
|
+
test("shows the overview skeleton and fires every page request at once", async () => {
|
|
610
|
+
getListMock.mockReturnValue(new Promise<never>(() => {}) as never);
|
|
611
|
+
getItemMock.mockReturnValue(new Promise<never>(() => {}) as never);
|
|
612
|
+
|
|
613
|
+
render(<AlertEpisodeView {...pageProps} />);
|
|
614
|
+
|
|
615
|
+
const status: HTMLElement = screen.getByRole("status");
|
|
616
|
+
|
|
617
|
+
expect(status).toHaveTextContent("Loading episode");
|
|
618
|
+
expect(
|
|
619
|
+
screen
|
|
620
|
+
.getByTestId("event-overview-skeleton-stats")
|
|
621
|
+
.querySelectorAll(".bg-white"),
|
|
622
|
+
).toHaveLength(4);
|
|
623
|
+
|
|
624
|
+
// Nothing below the skeleton mounts (and fetches) until the page is ready.
|
|
625
|
+
expect(screen.queryByText("Episode Severity")).toBeNull();
|
|
626
|
+
expect(changeStateProps.current).toBeNull();
|
|
627
|
+
|
|
628
|
+
// All four requests are in flight together rather than one after another.
|
|
629
|
+
expect(listCallsFor(Alert)).toHaveLength(1);
|
|
630
|
+
expect(listCallsFor(AlertEpisodeStateTimeline)).toHaveLength(1);
|
|
631
|
+
expect(listCallsFor(AlertState)).toHaveLength(1);
|
|
632
|
+
expect(getItemMock).toHaveBeenCalledTimes(1);
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
test("still reads the first member's telemetry snapshot, earliest created", async () => {
|
|
636
|
+
await renderPage({});
|
|
637
|
+
|
|
638
|
+
const firstMemberCall: Array<any> = listCallsFor(Alert).find(
|
|
639
|
+
(call: Array<any>): boolean => {
|
|
640
|
+
return call[0].limit === 1;
|
|
641
|
+
},
|
|
642
|
+
)!;
|
|
643
|
+
|
|
644
|
+
expect(firstMemberCall[0].query.alertEpisodeId.toString()).toBe(EPISODE_ID);
|
|
645
|
+
expect(firstMemberCall[0].select).toEqual({
|
|
646
|
+
_id: true,
|
|
647
|
+
telemetryQuery: true,
|
|
648
|
+
seriesLabels: true,
|
|
649
|
+
});
|
|
650
|
+
// Alerts have no declaredAt: the earliest created alert comes first.
|
|
651
|
+
expect(firstMemberCall[0].sort).toEqual({
|
|
652
|
+
createdAt: SortOrder.Ascending,
|
|
653
|
+
});
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
test("renders the header, a four-cell stat bar and the member list", async () => {
|
|
657
|
+
await renderPage({ state: buildState("Created", new Color("#4b5563")) });
|
|
658
|
+
|
|
659
|
+
expect(changeStateProps.current?.["episodeId"].toString()).toBe(EPISODE_ID);
|
|
660
|
+
|
|
661
|
+
const statBar: HTMLElement = screen.getByRole("group", {
|
|
662
|
+
name: "Episode timing",
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
expect(within(statBar).getByText("Acknowledged in")).toBeInTheDocument();
|
|
666
|
+
expect(within(statBar).getByText("Resolved in")).toBeInTheDocument();
|
|
667
|
+
expect(within(statBar).getByText("Duration")).toBeInTheDocument();
|
|
668
|
+
expect(within(statBar).getByText("Alerts")).toBeInTheDocument();
|
|
669
|
+
expect(statValue("Alerts")).toBe("0");
|
|
670
|
+
|
|
671
|
+
await waitFor((): void => {
|
|
672
|
+
expect(
|
|
673
|
+
screen.getByText("No alerts in this episode yet"),
|
|
674
|
+
).toBeInTheDocument();
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
const memberCall: Array<any> = listCallsFor(Alert).find(
|
|
678
|
+
(call: Array<any>): boolean => {
|
|
679
|
+
return call[0].limit === 8;
|
|
680
|
+
},
|
|
681
|
+
)!;
|
|
682
|
+
|
|
683
|
+
expect(memberCall[0].query.alertEpisodeId.toString()).toBe(EPISODE_ID);
|
|
684
|
+
expect(memberCall[0].sort).toEqual({ createdAt: SortOrder.Descending });
|
|
685
|
+
expectNoCrash();
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
test("measures the stat bar from createdAt with the project's state names", async () => {
|
|
689
|
+
const startedAt: Date = new Date("2026-09-14T18:00:00.000Z");
|
|
690
|
+
|
|
691
|
+
const ackState: AlertState = new AlertState();
|
|
692
|
+
ackState.id = new ObjectID(ACK_STATE_ID);
|
|
693
|
+
ackState.name = "Triaged";
|
|
694
|
+
ackState.isAcknowledgedState = true;
|
|
695
|
+
|
|
696
|
+
const resolvedState: AlertState = new AlertState();
|
|
697
|
+
resolvedState.id = new ObjectID(RESOLVED_STATE_ID);
|
|
698
|
+
resolvedState.name = "Fixed";
|
|
699
|
+
resolvedState.isResolvedState = true;
|
|
700
|
+
|
|
701
|
+
const ackTimeline: AlertEpisodeStateTimeline =
|
|
702
|
+
new AlertEpisodeStateTimeline();
|
|
703
|
+
ackTimeline.alertStateId = new ObjectID(ACK_STATE_ID);
|
|
704
|
+
// Written long after creation, so a first-timeline start would be wrong.
|
|
705
|
+
ackTimeline.startsAt = new Date(startedAt.getTime() + 42 * 60 * 1000);
|
|
706
|
+
|
|
707
|
+
const resolvedTimeline: AlertEpisodeStateTimeline =
|
|
708
|
+
new AlertEpisodeStateTimeline();
|
|
709
|
+
resolvedTimeline.alertStateId = new ObjectID(RESOLVED_STATE_ID);
|
|
710
|
+
resolvedTimeline.startsAt = new Date(startedAt.getTime() + 125 * 60 * 1000);
|
|
711
|
+
|
|
712
|
+
getListMock.mockImplementation((...args: Array<any>) => {
|
|
713
|
+
const modelType: unknown = args[0]?.modelType;
|
|
714
|
+
|
|
715
|
+
if (modelType === AlertState) {
|
|
716
|
+
return Promise.resolve({
|
|
717
|
+
data: [ackState, resolvedState],
|
|
718
|
+
count: 2,
|
|
719
|
+
skip: 0,
|
|
720
|
+
limit: 2,
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
if (modelType === AlertEpisodeStateTimeline) {
|
|
725
|
+
return Promise.resolve({
|
|
726
|
+
data: [resolvedTimeline, ackTimeline],
|
|
727
|
+
count: 2,
|
|
728
|
+
skip: 0,
|
|
729
|
+
limit: 2,
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
return Promise.resolve(emptyList());
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
const episode: AlertEpisode = buildEpisode({});
|
|
737
|
+
episode.createdAt = startedAt;
|
|
738
|
+
episode.alertCount = 3;
|
|
739
|
+
|
|
740
|
+
getItemMock.mockResolvedValue(episode as never);
|
|
741
|
+
|
|
742
|
+
render(<AlertEpisodeView {...pageProps} />);
|
|
743
|
+
|
|
744
|
+
await waitFor((): void => {
|
|
745
|
+
expect(screen.getByText("Triaged in")).toBeInTheDocument();
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
expect(statValue("Triaged in")).toBe("42 minutes");
|
|
749
|
+
expect(statValue("Fixed in")).toBe("2 hours, 5 minutes");
|
|
750
|
+
// Resolved now, so the duration is closed: created -> resolved.
|
|
751
|
+
expect(statValue("Duration")).toBe("2 hours, 5 minutes");
|
|
752
|
+
expect(statValue("Alerts")).toBe("3");
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
test("a state change refreshes the page in place instead of unmounting it", async () => {
|
|
756
|
+
await renderPage({ state: buildState("Created", new Color("#4b5563")) });
|
|
757
|
+
|
|
758
|
+
await waitFor((): void => {
|
|
759
|
+
expect(
|
|
760
|
+
screen.getByText("No alerts in this episode yet"),
|
|
761
|
+
).toBeInTheDocument();
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
const timelineCallsBefore: number = listCallsFor(
|
|
765
|
+
AlertEpisodeStateTimeline,
|
|
766
|
+
).length;
|
|
767
|
+
const memberCallsBefore: number = listCallsFor(Alert).filter(
|
|
768
|
+
(call: Array<any>): boolean => {
|
|
769
|
+
return call[0].limit === 8;
|
|
770
|
+
},
|
|
771
|
+
).length;
|
|
772
|
+
const detailFetchesBefore: number = getItemMock.mock.calls.length;
|
|
773
|
+
|
|
774
|
+
let pending: Promise<void> | undefined;
|
|
775
|
+
|
|
776
|
+
act(() => {
|
|
777
|
+
pending = changeStateProps.current!["onActionComplete"]();
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
// No skeleton, no loader: the stat bar and header stay on screen.
|
|
781
|
+
expect(screen.queryByText("Loading episode")).toBeNull();
|
|
782
|
+
expect(
|
|
783
|
+
screen.getByRole("group", { name: "Episode timing" }),
|
|
784
|
+
).toBeInTheDocument();
|
|
785
|
+
|
|
786
|
+
await act(async () => {
|
|
787
|
+
await pending;
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
await waitFor((): void => {
|
|
791
|
+
expect(listCallsFor(AlertEpisodeStateTimeline).length).toBe(
|
|
792
|
+
timelineCallsBefore + 1,
|
|
793
|
+
);
|
|
794
|
+
// The member list reloads too: member states moved with the episode.
|
|
795
|
+
expect(
|
|
796
|
+
listCallsFor(Alert).filter((call: Array<any>): boolean => {
|
|
797
|
+
return call[0].limit === 8;
|
|
798
|
+
}).length,
|
|
799
|
+
).toBe(memberCallsBefore + 1);
|
|
800
|
+
// Page timing getItem plus the details card reload.
|
|
801
|
+
expect(getItemMock.mock.calls.length).toBeGreaterThanOrEqual(
|
|
802
|
+
detailFetchesBefore + 2,
|
|
803
|
+
);
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
expect(screen.getByText("Episode Severity")).toBeInTheDocument();
|
|
463
807
|
expectNoCrash();
|
|
464
808
|
});
|
|
809
|
+
|
|
810
|
+
test("a failed first load offers a retry that recovers", async () => {
|
|
811
|
+
getItemMock.mockResolvedValue(buildEpisode({}) as never);
|
|
812
|
+
getListMock.mockRejectedValueOnce(new Error("Episode service down"));
|
|
813
|
+
|
|
814
|
+
render(<AlertEpisodeView {...pageProps} />);
|
|
815
|
+
|
|
816
|
+
await waitFor((): void => {
|
|
817
|
+
expect(screen.getByText("Episode service down")).toBeInTheDocument();
|
|
818
|
+
});
|
|
819
|
+
|
|
820
|
+
fireEvent.click(screen.getByTestId("refresh-button"));
|
|
821
|
+
|
|
822
|
+
await waitFor((): void => {
|
|
823
|
+
expect(screen.getByText("Episode Severity")).toBeInTheDocument();
|
|
824
|
+
});
|
|
825
|
+
|
|
826
|
+
expect(screen.queryByText("Episode service down")).toBeNull();
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
test("a failed refresh keeps the page and says so inline", async () => {
|
|
830
|
+
await renderPage({ state: buildState("Created", new Color("#4b5563")) });
|
|
831
|
+
|
|
832
|
+
getListMock.mockRejectedValueOnce(new Error("Timeline unavailable"));
|
|
833
|
+
|
|
834
|
+
await act(async () => {
|
|
835
|
+
await changeStateProps.current!["onActionComplete"]();
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
await waitFor((): void => {
|
|
839
|
+
expect(screen.getByRole("alert")).toHaveTextContent(
|
|
840
|
+
"Couldn't refresh episode timings: Timeline unavailable",
|
|
841
|
+
);
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
expect(
|
|
845
|
+
screen.getByRole("group", { name: "Episode timing" }),
|
|
846
|
+
).toBeInTheDocument();
|
|
847
|
+
expect(screen.getByText("Episode Severity")).toBeInTheDocument();
|
|
848
|
+
});
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
describe("Alert Episode overview: moving to another episode on the same route", () => {
|
|
852
|
+
/*
|
|
853
|
+
* The overview is an index route inside the episode layout, so moving to
|
|
854
|
+
* another episode re-renders this page with a new id instead of remounting
|
|
855
|
+
* it. The first render for the new id used to mount the header, the member
|
|
856
|
+
* list and the details card for the new id over the previous episode's
|
|
857
|
+
* numbers (each one fetching) before an effect flipped back to the skeleton.
|
|
858
|
+
*/
|
|
859
|
+
const OTHER_EPISODE_ID: string = "99999999-9999-4999-8999-999999999999";
|
|
860
|
+
|
|
861
|
+
type NavigateToFunction = (episodeId: string) => void;
|
|
862
|
+
|
|
863
|
+
const navigateTo: NavigateToFunction = (episodeId: string): void => {
|
|
864
|
+
const path: string = `/dashboard/${PROJECT_ID}/alerts/episodes/${episodeId}`;
|
|
865
|
+
|
|
866
|
+
window.history.pushState({}, "", path);
|
|
867
|
+
Navigation.setLocation({
|
|
868
|
+
pathname: path,
|
|
869
|
+
search: "",
|
|
870
|
+
hash: "",
|
|
871
|
+
state: null,
|
|
872
|
+
key: "other",
|
|
873
|
+
} as Location);
|
|
874
|
+
};
|
|
875
|
+
|
|
876
|
+
// The page's own timing read asks for resolvedAt; the details card does not.
|
|
877
|
+
type IsPageReadFunction = (call: Array<any>) => boolean;
|
|
878
|
+
|
|
879
|
+
const isPageRead: IsPageReadFunction = (call: Array<any>): boolean => {
|
|
880
|
+
return call[0]?.select?.resolvedAt === true;
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
type ReadsForFunction = (
|
|
884
|
+
episodeId: string,
|
|
885
|
+
predicate: IsPageReadFunction,
|
|
886
|
+
) => number;
|
|
887
|
+
|
|
888
|
+
const readsFor: ReadsForFunction = (
|
|
889
|
+
episodeId: string,
|
|
890
|
+
predicate: IsPageReadFunction,
|
|
891
|
+
): number => {
|
|
892
|
+
return getItemMock.mock.calls.filter((call: Array<any>): boolean => {
|
|
893
|
+
return call[0]?.id?.toString() === episodeId && predicate(call);
|
|
894
|
+
}).length;
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
type ServeEpisodesFunction = (otherPageRead: Promise<AlertEpisode>) => void;
|
|
898
|
+
|
|
899
|
+
const serveEpisodes: ServeEpisodesFunction = (
|
|
900
|
+
otherPageRead: Promise<AlertEpisode>,
|
|
901
|
+
): void => {
|
|
902
|
+
getItemMock.mockImplementation((...args: Array<any>) => {
|
|
903
|
+
const request: Record<string, any> = args[0];
|
|
904
|
+
|
|
905
|
+
if (request["id"]?.toString() === OTHER_EPISODE_ID && isPageRead(args)) {
|
|
906
|
+
return otherPageRead;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
const episode: AlertEpisode = buildEpisode({
|
|
910
|
+
state: buildState("Created", new Color("#4b5563")),
|
|
911
|
+
});
|
|
912
|
+
|
|
913
|
+
if (request["id"]?.toString() === OTHER_EPISODE_ID) {
|
|
914
|
+
episode.id = new ObjectID(OTHER_EPISODE_ID);
|
|
915
|
+
episode.alertCount = 5;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
return Promise.resolve(episode);
|
|
919
|
+
});
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
test("shows the skeleton first and renders nothing for the new id before its numbers land", async () => {
|
|
923
|
+
let resolveOther: (episode: AlertEpisode) => void = (): void => {};
|
|
924
|
+
const otherPageRead: Promise<AlertEpisode> = new Promise<AlertEpisode>(
|
|
925
|
+
(resolve: (episode: AlertEpisode) => void) => {
|
|
926
|
+
resolveOther = resolve;
|
|
927
|
+
},
|
|
928
|
+
);
|
|
929
|
+
|
|
930
|
+
serveEpisodes(otherPageRead);
|
|
931
|
+
|
|
932
|
+
const view: ReturnType<typeof render> = render(
|
|
933
|
+
<AlertEpisodeView {...pageProps} />,
|
|
934
|
+
);
|
|
935
|
+
|
|
936
|
+
await waitFor((): void => {
|
|
937
|
+
expect(screen.getByText("Episode Severity")).toBeInTheDocument();
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
const headerRendersBefore: number = changeStateHistory.length;
|
|
941
|
+
|
|
942
|
+
navigateTo(OTHER_EPISODE_ID);
|
|
943
|
+
view.rerender(<AlertEpisodeView {...pageProps} />);
|
|
944
|
+
|
|
945
|
+
expect(screen.getByRole("status")).toHaveTextContent("Loading episode");
|
|
946
|
+
expect(screen.queryByText("Episode Severity")).toBeNull();
|
|
947
|
+
|
|
948
|
+
await waitFor((): void => {
|
|
949
|
+
expect(readsFor(OTHER_EPISODE_ID, isPageRead)).toBe(1);
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
// Neither the header nor the details card rendered for the new id yet.
|
|
953
|
+
expect(
|
|
954
|
+
changeStateHistory
|
|
955
|
+
.slice(headerRendersBefore)
|
|
956
|
+
.filter((props: Record<string, any>): boolean => {
|
|
957
|
+
return props["episodeId"]?.toString() === OTHER_EPISODE_ID;
|
|
958
|
+
}),
|
|
959
|
+
).toEqual([]);
|
|
960
|
+
expect(
|
|
961
|
+
readsFor(OTHER_EPISODE_ID, (call: Array<any>): boolean => {
|
|
962
|
+
return !isPageRead(call);
|
|
963
|
+
}),
|
|
964
|
+
).toBe(0);
|
|
965
|
+
|
|
966
|
+
const otherEpisode: AlertEpisode = buildEpisode({});
|
|
967
|
+
otherEpisode.id = new ObjectID(OTHER_EPISODE_ID);
|
|
968
|
+
otherEpisode.alertCount = 5;
|
|
969
|
+
|
|
970
|
+
await act(async () => {
|
|
971
|
+
resolveOther(otherEpisode);
|
|
972
|
+
});
|
|
973
|
+
|
|
974
|
+
await waitFor((): void => {
|
|
975
|
+
expect(statValue("Alerts")).toBe("5");
|
|
976
|
+
});
|
|
977
|
+
|
|
978
|
+
expect(changeStateProps.current?.["episodeId"].toString()).toBe(
|
|
979
|
+
OTHER_EPISODE_ID,
|
|
980
|
+
);
|
|
981
|
+
|
|
982
|
+
await waitFor((): void => {
|
|
983
|
+
expect(screen.getByText("Episode Severity")).toBeInTheDocument();
|
|
984
|
+
});
|
|
985
|
+
|
|
986
|
+
// The details card mounted once for the new episode: one read, not two.
|
|
987
|
+
expect(
|
|
988
|
+
readsFor(OTHER_EPISODE_ID, (call: Array<any>): boolean => {
|
|
989
|
+
return !isPageRead(call);
|
|
990
|
+
}),
|
|
991
|
+
).toBe(1);
|
|
992
|
+
expectNoCrash();
|
|
993
|
+
});
|
|
994
|
+
|
|
995
|
+
test("an action on the previous episode that finishes after the switch cannot cancel the next one's load", async () => {
|
|
996
|
+
let resolveOther: (episode: AlertEpisode) => void = (): void => {};
|
|
997
|
+
const otherPageRead: Promise<AlertEpisode> = new Promise<AlertEpisode>(
|
|
998
|
+
(resolve: (episode: AlertEpisode) => void) => {
|
|
999
|
+
resolveOther = resolve;
|
|
1000
|
+
},
|
|
1001
|
+
);
|
|
1002
|
+
|
|
1003
|
+
serveEpisodes(otherPageRead);
|
|
1004
|
+
|
|
1005
|
+
const view: ReturnType<typeof render> = render(
|
|
1006
|
+
<AlertEpisodeView {...pageProps} />,
|
|
1007
|
+
);
|
|
1008
|
+
|
|
1009
|
+
await waitFor((): void => {
|
|
1010
|
+
expect(screen.getByText("Episode Severity")).toBeInTheDocument();
|
|
1011
|
+
});
|
|
1012
|
+
|
|
1013
|
+
// Handed to the previous episode's header, which can still call it.
|
|
1014
|
+
const previousOnActionComplete: () => Promise<void> =
|
|
1015
|
+
changeStateProps.current!["onActionComplete"];
|
|
1016
|
+
|
|
1017
|
+
navigateTo(OTHER_EPISODE_ID);
|
|
1018
|
+
view.rerender(<AlertEpisodeView {...pageProps} />);
|
|
1019
|
+
|
|
1020
|
+
await waitFor((): void => {
|
|
1021
|
+
expect(readsFor(OTHER_EPISODE_ID, isPageRead)).toBe(1);
|
|
1022
|
+
});
|
|
1023
|
+
|
|
1024
|
+
const timelineReadsBefore: number = listCallsFor(
|
|
1025
|
+
AlertEpisodeStateTimeline,
|
|
1026
|
+
).length;
|
|
1027
|
+
const previousPageReadsBefore: number = readsFor(EPISODE_ID, isPageRead);
|
|
1028
|
+
|
|
1029
|
+
await act(async () => {
|
|
1030
|
+
await previousOnActionComplete();
|
|
1031
|
+
});
|
|
1032
|
+
|
|
1033
|
+
// Nothing was read again for the episode the reader already left.
|
|
1034
|
+
expect(listCallsFor(AlertEpisodeStateTimeline).length).toBe(
|
|
1035
|
+
timelineReadsBefore,
|
|
1036
|
+
);
|
|
1037
|
+
expect(readsFor(EPISODE_ID, isPageRead)).toBe(previousPageReadsBefore);
|
|
1038
|
+
|
|
1039
|
+
const otherEpisode: AlertEpisode = buildEpisode({});
|
|
1040
|
+
otherEpisode.id = new ObjectID(OTHER_EPISODE_ID);
|
|
1041
|
+
otherEpisode.alertCount = 5;
|
|
1042
|
+
|
|
1043
|
+
await act(async () => {
|
|
1044
|
+
resolveOther(otherEpisode);
|
|
1045
|
+
});
|
|
1046
|
+
|
|
1047
|
+
await waitFor((): void => {
|
|
1048
|
+
expect(statValue("Alerts")).toBe("5");
|
|
1049
|
+
});
|
|
1050
|
+
});
|
|
465
1051
|
});
|