@oneuptime/common 12.0.23 → 12.0.24
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/DetectionRule.ts +55 -0
- package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +27 -7
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +67 -0
- package/Models/DatabaseModels/Project.ts +68 -0
- package/Models/DatabaseModels/User.ts +68 -0
- package/Server/API/TelemetryAPI.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.ts +28 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.ts +49 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/GzipRequestBody.ts +311 -0
- package/Server/Middleware/MultipartFormData.ts +87 -3
- package/Server/Services/DetectionRuleService.ts +73 -6
- package/Server/Services/Index.ts +205 -0
- package/Server/Services/NetworkDeviceDiscoveryScanService.ts +59 -0
- package/Server/Services/NetworkDeviceService.ts +148 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
- package/Server/Services/OnCallDutyPolicyFeedService.ts +1 -1
- package/Server/Services/ProjectService.ts +29 -19
- package/Server/Services/SecurityEventService.ts +90 -13
- package/Server/Services/StatusPageResourceService.ts +223 -0
- package/Server/Services/TelemetryAttributeService.ts +17 -0
- package/Server/Services/UserService.ts +4 -6
- package/Server/Types/Markdown.ts +161 -67
- package/Server/Utils/AI/Toolbox/OnCallTools.ts +12 -4
- package/Server/Utils/AnalyticsDatabase/Statement.ts +13 -1
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +297 -6
- package/Server/Utils/Attribution.ts +4 -0
- package/Server/Utils/Marketing/MarketingEventUtil.ts +45 -7
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +55 -3
- package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +21 -0
- package/Server/Utils/StartServer.ts +12 -32
- package/Server/Utils/Telemetry/LlmCostBudgetEvaluator.ts +101 -4
- package/Server/Utils/Telemetry/LlmMetricSpend.ts +130 -0
- package/Server/Views/Partials/AnalyticsConsent.ejs +159 -102
- package/Server/Views/Partials/Head.ejs +2 -1
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +776 -38
- package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +359 -0
- package/Tests/App/Dashboard/CorrelateGraph.test.tsx +865 -0
- package/Tests/App/Dashboard/CorrelationGraph.test.ts +346 -0
- package/Tests/App/Dashboard/CriteriaFilterConditionDropdown.test.tsx +256 -0
- package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +738 -0
- package/Tests/App/Dashboard/CriteriaFilterMonitorTypeChange.test.ts +1122 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +283 -0
- package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +407 -0
- package/Tests/App/Dashboard/MetricSeriesInvestigateMenu.test.tsx +5 -14
- package/Tests/App/Dashboard/MonitorCriteriaActionToggles.test.tsx +426 -0
- package/Tests/App/Dashboard/MonitorStepsCriteriaAlignmentWiring.test.tsx +352 -0
- package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +278 -0
- package/Tests/App/Dashboard/OnCallLayerShiftPreviewOverrides.test.ts +237 -0
- package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +2 -2
- package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +460 -0
- package/Tests/App/Dashboard/SecurityEventAttributeUtil.test.ts +171 -0
- package/Tests/App/Dashboard/SecurityEventCorrelation.test.ts +857 -0
- package/Tests/App/Dashboard/SecurityEventDetailObservables.test.tsx +194 -0
- package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +124 -0
- package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +79 -19
- package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +382 -0
- package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +216 -0
- package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +590 -11
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +757 -0
- package/Tests/Models/DiscoveryScanNameColumn.test.ts +293 -0
- package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +564 -0
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +120 -4
- package/Tests/Server/Middleware/GzipRequestBody.test.ts +725 -0
- package/Tests/Server/Middleware/MultipartFormData.test.ts +298 -0
- package/Tests/Server/Services/AddDetectionRuleDistinctCountColumnsMigration.test.ts +311 -0
- package/Tests/Server/Services/DetectionRuleService.test.ts +134 -2
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +7 -1
- package/Tests/Server/Services/FeedRetentionConsistency.test.ts +131 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +194 -0
- package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +800 -0
- package/Tests/Server/Services/OnCallScheduleAttachRosterRefresh.test.ts +244 -0
- package/Tests/Server/Services/SecurityEventService.test.ts +376 -0
- package/Tests/Server/Services/StatusPageResourceDuplicates.test.ts +703 -0
- package/Tests/Server/Services/TelemetryAttributeServiceSecurityEvent.test.ts +256 -0
- package/Tests/Server/Types/Workflow/Components/ComponentRegistryParity.test.ts +417 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWhereOperators.test.ts +677 -0
- package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +43 -0
- package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +15 -11
- package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +369 -8
- package/Tests/Server/Utils/SecurityEvent/SigmaClickhouseCompiler.test.ts +35 -0
- package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +368 -4
- package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +245 -0
- package/Tests/Server/Views/AnalyticsConsentPartial.test.ts +48 -5
- package/Tests/Types/Code/YamlSyntax.test.ts +396 -0
- package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +957 -0
- package/Tests/Types/Monitor/MonitorCriteriaActionValidation.test.ts +598 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +49 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +6 -6
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +4 -4
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +4 -3
- package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +193 -0
- package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +0 -12
- package/Tests/UI/Components/CardModelDetailEdit.test.tsx +1 -17
- package/Tests/UI/Components/CodeEditor.test.tsx +474 -10
- package/Tests/UI/Components/Detail/YamlField.test.tsx +105 -0
- package/Tests/UI/Components/EntityDropdownLabelsBulkAdd.test.tsx +319 -0
- package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +231 -0
- package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +1 -0
- package/Tests/UI/Components/Forms/ValidationYAML.test.ts +234 -0
- package/Tests/UI/Components/ModelTable/AttributeColumns.test.tsx +573 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableAttributeColumns.test.tsx +824 -0
- package/Tests/UI/Components/ModelTable/ColumnCustomizationModalAddableColumns.test.tsx +707 -0
- package/Tests/UI/Components/SideOver.test.tsx +1 -1
- package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +294 -0
- package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +436 -0
- package/Tests/UI/Components/TableBulkCsvExport.test.tsx +6 -2
- package/Tests/UI/Components/Toggle.test.tsx +25 -0
- package/Tests/UI/Components/YamlEditor.test.tsx +847 -0
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +252 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +221 -0
- package/Tests/Utils/NetworkDiscovery/ScanNameUtil.test.ts +312 -0
- package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +468 -0
- package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +472 -0
- package/Types/Code/YamlSyntax.ts +396 -0
- package/Types/Exception/ExceptionCode.ts +1 -0
- package/Types/Exception/PayloadTooLargeException.ts +8 -0
- package/Types/Marketing/Attribution.ts +10 -0
- package/Types/Marketing/MarketingEvent.ts +4 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +116 -56
- package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +2 -1
- package/Types/SecurityEvent/DetectionFindingConstants.ts +11 -0
- package/Types/Telemetry/LlmMetricConventions.ts +124 -0
- package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +3 -0
- package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +10 -1
- package/UI/Components/CodeEditor/CodeEditor.tsx +241 -79
- package/UI/Components/CodeEditor/YamlEditor.tsx +369 -0
- package/UI/Components/Detail/Detail.tsx +10 -0
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +33 -0
- package/UI/Components/Forms/Fields/FormField.tsx +31 -0
- package/UI/Components/Forms/Types/Field.ts +8 -0
- package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
- package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -0
- package/UI/Components/Forms/Validation.ts +46 -0
- package/UI/Components/Input/Input.tsx +3 -0
- package/UI/Components/ModelTable/AttributeColumns.tsx +321 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +263 -14
- package/UI/Components/ModelTable/Column.ts +8 -0
- package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +310 -0
- package/UI/Components/ModelTable/ColumnPreference.ts +13 -1
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +2 -2
- package/UI/Components/SideOver/SideOver.tsx +5 -5
- package/UI/Components/StatusPage/ResourceGrid.tsx +82 -2
- package/UI/Components/StatusPage/ResourceList.tsx +197 -38
- package/UI/Components/Toggle/Toggle.tsx +9 -1
- package/UI/Components/Types/FieldType.ts +1 -0
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +73 -1
- package/Utils/NetworkDiscovery/ScanNameUtil.ts +181 -0
- package/Utils/StatusPage/ResourceExplorer.ts +258 -0
- package/Utils/Telemetry/LlmMetricQuery.ts +204 -0
- package/build/dist/Models/DatabaseModels/DetectionRule.js +57 -0
- package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +27 -7
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +69 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +76 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/User.js +76 -0
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +17 -0
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js +21 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js +42 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.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/GzipRequestBody.js +224 -0
- package/build/dist/Server/Middleware/GzipRequestBody.js.map +1 -0
- package/build/dist/Server/Middleware/MultipartFormData.js +71 -2
- package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
- package/build/dist/Server/Services/DetectionRuleService.js +49 -4
- package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +204 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +50 -0
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +124 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +68 -13
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +25 -45
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/SecurityEventService.js +57 -5
- package/build/dist/Server/Services/SecurityEventService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageResourceService.js +140 -0
- package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryAttributeService.js +17 -0
- package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +2 -12
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +147 -61
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +12 -4
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +12 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +246 -9
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Attribution.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +27 -7
- package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +42 -7
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +18 -0
- package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +12 -21
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js +76 -5
- package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +102 -0
- package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -0
- package/build/dist/Types/Code/YamlSyntax.js +212 -0
- package/build/dist/Types/Code/YamlSyntax.js.map +1 -0
- package/build/dist/Types/Exception/ExceptionCode.js +1 -0
- package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
- package/build/dist/Types/Exception/PayloadTooLargeException.js +8 -0
- package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -0
- package/build/dist/Types/Marketing/Attribution.js +10 -0
- package/build/dist/Types/Marketing/Attribution.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +112 -51
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +2 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
- package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +9 -0
- package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
- package/build/dist/Types/Telemetry/LlmMetricConventions.js +98 -0
- package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -0
- package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
- package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +5 -2
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +206 -76
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js +201 -0
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -0
- package/build/dist/UI/Components/Detail/Detail.js +9 -0
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +16 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +14 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
- package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
- package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -0
- package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
- package/build/dist/UI/Components/Forms/Validation.js +27 -0
- package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +1 -1
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/AttributeColumns.js +159 -0
- package/build/dist/UI/Components/ModelTable/AttributeColumns.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +179 -17
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +133 -2
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js +7 -1
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +2 -2
- package/build/dist/UI/Components/SideOver/SideOver.js +5 -5
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js +28 -2
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceList.js +87 -20
- package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
- package/build/dist/UI/Components/Toggle/Toggle.js +9 -1
- package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
- package/build/dist/UI/Components/Types/FieldType.js +1 -0
- package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +37 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js +120 -0
- package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js.map +1 -0
- package/build/dist/Utils/StatusPage/ResourceExplorer.js +171 -0
- package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -1
- package/build/dist/Utils/Telemetry/LlmMetricQuery.js +119 -0
- package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -0
- package/jest.config.json +2 -0
- package/package.json +1 -1
- package/tsconfig.json +2 -1
- package/Tests/UI/Components/Toast.test.tsx +0 -197
- package/Tests/UI/Components/ToastStacking.test.tsx +0 -198
- package/UI/Components/Toast/Toast.tsx +0 -189
- package/UI/Components/Toast/ToastInit.tsx +0 -110
- package/build/dist/UI/Components/Toast/Toast.js +0 -123
- package/build/dist/UI/Components/Toast/Toast.js.map +0 -1
- package/build/dist/UI/Components/Toast/ToastInit.js +0 -53
- package/build/dist/UI/Components/Toast/ToastInit.js.map +0 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import {
|
|
5
|
+
afterEach,
|
|
6
|
+
beforeEach,
|
|
7
|
+
describe,
|
|
8
|
+
expect,
|
|
9
|
+
jest,
|
|
10
|
+
test,
|
|
11
|
+
} from "@jest/globals";
|
|
12
|
+
import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* The security event detail panel renders observables as pivot chips: with
|
|
16
|
+
* an onCorrelateObservable handler (the Correlate page embeds it that way)
|
|
17
|
+
* a chip pivots in place; without one (the events table) a chip deep-links
|
|
18
|
+
* to the Correlate page with the observable pre-seeded — URL-encoded, since
|
|
19
|
+
* Route.addQueryParams does not encode.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const navigateMock: MockFunction = getJestMockFunction();
|
|
23
|
+
|
|
24
|
+
jest.mock("../../../UI/Utils/Navigation", () => {
|
|
25
|
+
return {
|
|
26
|
+
__esModule: true,
|
|
27
|
+
default: {
|
|
28
|
+
navigate: (...args: Array<any>) => {
|
|
29
|
+
return navigateMock(...args);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
jest.mock("../../../../App/FeatureSet/Dashboard/src/Utils/RouteMap", () => {
|
|
36
|
+
/*
|
|
37
|
+
* The mocked route keeps its :projectId placeholder and only the mocked
|
|
38
|
+
* populateRouteParams substitutes it — so the exact-URL assertions below
|
|
39
|
+
* fail if the component ever skips populateRouteParams.
|
|
40
|
+
*/
|
|
41
|
+
const routeMap: Record<string, unknown> = {};
|
|
42
|
+
routeMap[PageMap.SECURITY_EVENTS_CORRELATE] = new Route(
|
|
43
|
+
"/dashboard/:projectId/security-events/correlate",
|
|
44
|
+
);
|
|
45
|
+
return {
|
|
46
|
+
__esModule: true,
|
|
47
|
+
default: routeMap,
|
|
48
|
+
RouteUtil: {
|
|
49
|
+
/*
|
|
50
|
+
* Fresh Route per call — addQueryParams mutates the instance, and a
|
|
51
|
+
* shared one would leak query params across tests.
|
|
52
|
+
*/
|
|
53
|
+
populateRouteParams: (route: { toString: () => string }) => {
|
|
54
|
+
return new Route(
|
|
55
|
+
route.toString().replace(":projectId", "mock-project"),
|
|
56
|
+
);
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/*
|
|
63
|
+
* The component import comes LAST: requiring it instantiates the mock
|
|
64
|
+
* factories above, which reference Route and PageMap — so those must be
|
|
65
|
+
* initialized first.
|
|
66
|
+
*/
|
|
67
|
+
import SecurityEvent from "../../../Models/AnalyticsModels/SecurityEvent";
|
|
68
|
+
import Route from "../../../Types/API/Route";
|
|
69
|
+
import OcsfSeverity from "../../../Types/SecurityEvent/OcsfSeverity";
|
|
70
|
+
import PageMap from "../../../../App/FeatureSet/Dashboard/src/Utils/PageMap";
|
|
71
|
+
import SecurityEventDetail from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/SecurityEventDetail";
|
|
72
|
+
|
|
73
|
+
function buildEvent(observables: Array<string>): SecurityEvent {
|
|
74
|
+
const event: SecurityEvent = new SecurityEvent();
|
|
75
|
+
event.className = "Authentication";
|
|
76
|
+
event.severityName = OcsfSeverity.High;
|
|
77
|
+
event.message = "failed password for alice";
|
|
78
|
+
event.observables = observables;
|
|
79
|
+
return event;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
beforeEach(() => {
|
|
83
|
+
navigateMock.mockReset();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
afterEach(() => {
|
|
87
|
+
cleanup();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe("SecurityEventDetail observables", () => {
|
|
91
|
+
test("renders one chip per observable", () => {
|
|
92
|
+
render(
|
|
93
|
+
<SecurityEventDetail
|
|
94
|
+
securityEvent={buildEvent(["wb-ubuntu-03", "alice", "192.168.1.20"])}
|
|
95
|
+
onClose={() => {
|
|
96
|
+
return;
|
|
97
|
+
}}
|
|
98
|
+
/>,
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
expect(
|
|
102
|
+
screen.getByTestId("security-event-observable-chip-0"),
|
|
103
|
+
).toHaveTextContent("wb-ubuntu-03");
|
|
104
|
+
expect(
|
|
105
|
+
screen.getByTestId("security-event-observable-chip-1"),
|
|
106
|
+
).toHaveTextContent("alice");
|
|
107
|
+
expect(
|
|
108
|
+
screen.getByTestId("security-event-observable-chip-2"),
|
|
109
|
+
).toHaveTextContent("192.168.1.20");
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("empty observable strings render no chip, and no observables hides the row", () => {
|
|
113
|
+
render(
|
|
114
|
+
<SecurityEventDetail
|
|
115
|
+
securityEvent={buildEvent(["", "alice"])}
|
|
116
|
+
onClose={() => {
|
|
117
|
+
return;
|
|
118
|
+
}}
|
|
119
|
+
/>,
|
|
120
|
+
);
|
|
121
|
+
expect(
|
|
122
|
+
screen.getByTestId("security-event-observable-chip-0"),
|
|
123
|
+
).toHaveTextContent("alice");
|
|
124
|
+
expect(screen.queryByTestId("security-event-observable-chip-1")).toBeNull();
|
|
125
|
+
|
|
126
|
+
cleanup();
|
|
127
|
+
|
|
128
|
+
render(
|
|
129
|
+
<SecurityEventDetail
|
|
130
|
+
securityEvent={buildEvent([])}
|
|
131
|
+
onClose={() => {
|
|
132
|
+
return;
|
|
133
|
+
}}
|
|
134
|
+
/>,
|
|
135
|
+
);
|
|
136
|
+
expect(screen.queryByText("Observables")).toBeNull();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("with an onCorrelateObservable handler, a chip pivots in place instead of navigating", () => {
|
|
140
|
+
const onCorrelateMock: MockFunction = getJestMockFunction();
|
|
141
|
+
|
|
142
|
+
render(
|
|
143
|
+
<SecurityEventDetail
|
|
144
|
+
securityEvent={buildEvent(["wb-ubuntu-03"])}
|
|
145
|
+
onClose={() => {
|
|
146
|
+
return;
|
|
147
|
+
}}
|
|
148
|
+
onCorrelateObservable={onCorrelateMock as (observable: string) => void}
|
|
149
|
+
/>,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
fireEvent.click(screen.getByTestId("security-event-observable-chip-0"));
|
|
153
|
+
|
|
154
|
+
expect(onCorrelateMock).toHaveBeenCalledWith("wb-ubuntu-03");
|
|
155
|
+
expect(navigateMock).not.toHaveBeenCalled();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("without a handler, a chip deep-links to Correlate with the observable pre-seeded", () => {
|
|
159
|
+
render(
|
|
160
|
+
<SecurityEventDetail
|
|
161
|
+
securityEvent={buildEvent(["wb-ubuntu-03"])}
|
|
162
|
+
onClose={() => {
|
|
163
|
+
return;
|
|
164
|
+
}}
|
|
165
|
+
/>,
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
fireEvent.click(screen.getByTestId("security-event-observable-chip-0"));
|
|
169
|
+
|
|
170
|
+
expect(navigateMock).toHaveBeenCalledTimes(1);
|
|
171
|
+
const route: Route = navigateMock.mock.calls[0]?.[0] as Route;
|
|
172
|
+
expect(route.toString()).toBe(
|
|
173
|
+
"/dashboard/mock-project/security-events/correlate?observable=wb-ubuntu-03",
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test("observable values are URL-encoded into the deep link", () => {
|
|
178
|
+
render(
|
|
179
|
+
<SecurityEventDetail
|
|
180
|
+
securityEvent={buildEvent(["svc account&admin"])}
|
|
181
|
+
onClose={() => {
|
|
182
|
+
return;
|
|
183
|
+
}}
|
|
184
|
+
/>,
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
fireEvent.click(screen.getByTestId("security-event-observable-chip-0"));
|
|
188
|
+
|
|
189
|
+
const route: Route = navigateMock.mock.calls[0]?.[0] as Route;
|
|
190
|
+
expect(route.toString()).toContain(
|
|
191
|
+
`observable=${encodeURIComponent("svc account&admin")}`,
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
@@ -24,6 +24,10 @@ import { MemoryRouter } from "react-router-dom";
|
|
|
24
24
|
type CapturedFormField = {
|
|
25
25
|
field: Record<string, boolean>;
|
|
26
26
|
title: string;
|
|
27
|
+
fieldType?: unknown;
|
|
28
|
+
stepId?: string | undefined;
|
|
29
|
+
required?: boolean | undefined;
|
|
30
|
+
validation?: { minValue?: number | undefined } | undefined;
|
|
27
31
|
showIf?: ((model: Record<string, unknown>) => boolean) | undefined;
|
|
28
32
|
dropdownModal?: { type: unknown } | undefined;
|
|
29
33
|
};
|
|
@@ -43,6 +47,7 @@ type CapturedTableProps = {
|
|
|
43
47
|
formFields?: Array<CapturedFormField>;
|
|
44
48
|
actionButtons?: Array<CapturedActionButton>;
|
|
45
49
|
createInitialValues?: Record<string, unknown>;
|
|
50
|
+
helpContent?: { markdown?: string | undefined } | undefined;
|
|
46
51
|
};
|
|
47
52
|
|
|
48
53
|
let capturedTableProps: CapturedTableProps | null = null;
|
|
@@ -58,6 +63,7 @@ jest.mock("../../../UI/Components/ModelTable/ModelTable", () => {
|
|
|
58
63
|
});
|
|
59
64
|
|
|
60
65
|
import DetectionRulesPage from "../../../../App/FeatureSet/Dashboard/src/Pages/SecurityEvents/DetectionRules";
|
|
66
|
+
import FormFieldSchemaType from "../../../UI/Components/Forms/Types/FormFieldSchemaType";
|
|
61
67
|
import AlertSeverity from "../../../Models/DatabaseModels/AlertSeverity";
|
|
62
68
|
import IncidentSeverity from "../../../Models/DatabaseModels/IncidentSeverity";
|
|
63
69
|
import Project from "../../../Models/DatabaseModels/Project";
|
|
@@ -172,6 +178,124 @@ describe("Detection Rules page", () => {
|
|
|
172
178
|
});
|
|
173
179
|
});
|
|
174
180
|
|
|
181
|
+
describe("distinct count and match threshold fields", () => {
|
|
182
|
+
/*
|
|
183
|
+
* Issue #3398: a rule can now count unique values of one field
|
|
184
|
+
* (distinctCountField) instead of raw matching events, and hold fire
|
|
185
|
+
* until the count reaches matchCountThreshold. Both knobs are plain
|
|
186
|
+
* form configuration on the evaluation step — dropping either one is
|
|
187
|
+
* type-safe and render-safe, so the captured props are the only place
|
|
188
|
+
* they can be pinned.
|
|
189
|
+
*/
|
|
190
|
+
test("the Distinct Count Field is an optional text field", () => {
|
|
191
|
+
renderPage();
|
|
192
|
+
|
|
193
|
+
const field: CapturedFormField = fieldTitled("Distinct Count Field");
|
|
194
|
+
|
|
195
|
+
expect(field.field).toEqual({ distinctCountField: true });
|
|
196
|
+
expect(field.fieldType).toBe(FormFieldSchemaType.Text);
|
|
197
|
+
expect(field.required).toBe(false);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("the Match Count Threshold is a required number field that refuses values below 1", () => {
|
|
201
|
+
renderPage();
|
|
202
|
+
|
|
203
|
+
const field: CapturedFormField = fieldTitled("Match Count Threshold");
|
|
204
|
+
|
|
205
|
+
expect(field.field).toEqual({ matchCountThreshold: true });
|
|
206
|
+
expect(field.fieldType).toBe(FormFieldSchemaType.Number);
|
|
207
|
+
expect(field.required).toBe(true);
|
|
208
|
+
/*
|
|
209
|
+
* The service rejects 0 and negatives with a BadDataException; the
|
|
210
|
+
* form must stop them before submit.
|
|
211
|
+
*/
|
|
212
|
+
expect(field.validation?.minValue).toBe(1);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test("both new fields sit on the evaluation step alongside Group By Field", () => {
|
|
216
|
+
renderPage();
|
|
217
|
+
|
|
218
|
+
expect(fieldTitled("Group By Field").stepId).toBe("evaluation");
|
|
219
|
+
expect(fieldTitled("Distinct Count Field").stepId).toBe("evaluation");
|
|
220
|
+
expect(fieldTitled("Match Count Threshold").stepId).toBe("evaluation");
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test("a fresh create form seeds matchCountThreshold with the DB default of 1", () => {
|
|
224
|
+
/*
|
|
225
|
+
* matchCountThreshold is NOT NULL DEFAULT 1 in the schema and the
|
|
226
|
+
* form field is required — without this initial value a fresh
|
|
227
|
+
* create form would open with a required number field left blank.
|
|
228
|
+
*/
|
|
229
|
+
renderPage();
|
|
230
|
+
|
|
231
|
+
expect(capturedTableProps?.createInitialValues).toMatchObject({
|
|
232
|
+
matchCountThreshold: 1,
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
test("the help documentation explains both new controls", () => {
|
|
237
|
+
renderPage();
|
|
238
|
+
|
|
239
|
+
const markdown: string = capturedTableProps?.helpContent?.markdown || "";
|
|
240
|
+
|
|
241
|
+
expect(markdown).toContain("Distinct Count Field");
|
|
242
|
+
expect(markdown).toContain("Match Count Threshold");
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
describe("the Sigma rule field is a YAML editor", () => {
|
|
247
|
+
/*
|
|
248
|
+
* The rule is YAML — SigmaRuleParser runs js-yaml over it and
|
|
249
|
+
* DetectionRuleService rejects a create or update whose rule does not
|
|
250
|
+
* compile. It was declared as Markdown, which put a rich-text toolbar
|
|
251
|
+
* (Bold, H1) over a Sigma rule and, worse, routed the value through an
|
|
252
|
+
* editor that round-trips through HTML. Indentation-sensitive YAML does
|
|
253
|
+
* not survive that.
|
|
254
|
+
*/
|
|
255
|
+
test("it is declared as YAML", () => {
|
|
256
|
+
renderPage();
|
|
257
|
+
|
|
258
|
+
expect(fieldTitled("Sigma Rule (YAML)").fieldType).toBe(
|
|
259
|
+
FormFieldSchemaType.YAML,
|
|
260
|
+
);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("it is not the Markdown editor", () => {
|
|
264
|
+
renderPage();
|
|
265
|
+
|
|
266
|
+
expect(fieldTitled("Sigma Rule (YAML)").fieldType).not.toBe(
|
|
267
|
+
FormFieldSchemaType.Markdown,
|
|
268
|
+
);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
test("it still binds to sigmaRuleYaml on its own form step", () => {
|
|
272
|
+
renderPage();
|
|
273
|
+
|
|
274
|
+
const field: CapturedFormField = fieldTitled("Sigma Rule (YAML)");
|
|
275
|
+
|
|
276
|
+
expect(field.field).toEqual({ sigmaRuleYaml: true });
|
|
277
|
+
expect((field as unknown as { stepId?: string | undefined }).stepId).toBe(
|
|
278
|
+
"sigma-rule",
|
|
279
|
+
);
|
|
280
|
+
expect(
|
|
281
|
+
(field as unknown as { required?: boolean | undefined }).required,
|
|
282
|
+
).toBe(true);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test("no other field on the page was switched to YAML by accident", () => {
|
|
286
|
+
renderPage();
|
|
287
|
+
|
|
288
|
+
const yamlFields: Array<CapturedFormField> = (
|
|
289
|
+
capturedTableProps?.formFields || []
|
|
290
|
+
).filter((field: CapturedFormField): boolean => {
|
|
291
|
+
return field.fieldType === FormFieldSchemaType.YAML;
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
expect(yamlFields).toHaveLength(1);
|
|
295
|
+
expect(yamlFields[0]?.title).toBe("Sigma Rule (YAML)");
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
175
299
|
describe("Create Monitor row action", () => {
|
|
176
300
|
test("navigates to monitor create carrying the rule id", () => {
|
|
177
301
|
renderPage();
|
|
@@ -18,19 +18,24 @@ import ProjectUtil from "../../../UI/Utils/Project";
|
|
|
18
18
|
import ObjectID from "../../../Types/ObjectID";
|
|
19
19
|
|
|
20
20
|
/*
|
|
21
|
-
* The step form's field gating IS the feature here: Event Class
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* this
|
|
27
|
-
*
|
|
21
|
+
* The step form's field gating IS the feature here: Event Class and — as
|
|
22
|
+
* of issue #3398 — Event Severity live outside the "Show Advanced
|
|
23
|
+
* Options" toggle, because hiding them read as "monitors cannot filter
|
|
24
|
+
* by class/severity" to anyone who did not know the toggle existed.
|
|
25
|
+
* Only the service and attribute filters stay behind it. No other test
|
|
26
|
+
* renders this form (the view-model and type tests cover different
|
|
27
|
+
* layers), so without this one a refactor could quietly put a field
|
|
28
|
+
* back behind the toggle and nothing would fail.
|
|
28
29
|
*/
|
|
29
30
|
|
|
30
31
|
const PROJECT_ID: ObjectID = new ObjectID(
|
|
31
32
|
"11111111-1111-4111-8111-111111111111",
|
|
32
33
|
);
|
|
33
34
|
|
|
35
|
+
const TELEMETRY_SERVICE_ID: ObjectID = new ObjectID(
|
|
36
|
+
"22222222-2222-4222-8222-222222222222",
|
|
37
|
+
);
|
|
38
|
+
|
|
34
39
|
function renderForm(config?: Partial<MonitorStepSecurityEventsMonitor>): void {
|
|
35
40
|
render(
|
|
36
41
|
<SecurityEventsMonitorStepForm
|
|
@@ -58,20 +63,20 @@ describe("SecurityEventsMonitorStepForm field gating", () => {
|
|
|
58
63
|
jest.restoreAllMocks();
|
|
59
64
|
});
|
|
60
65
|
|
|
61
|
-
test("
|
|
66
|
+
test("severity and class are visible without opening advanced options", async () => {
|
|
62
67
|
renderForm();
|
|
63
68
|
|
|
64
69
|
// findBy: lets the preview's initial async count resolve inside act.
|
|
65
|
-
expect(await screen.findByText("Event
|
|
70
|
+
expect(await screen.findByText("Event Severity")).toBeInTheDocument();
|
|
71
|
+
expect(screen.getByText("Event Class")).toBeInTheDocument();
|
|
66
72
|
expect(screen.getByText("Show Advanced Options")).toBeInTheDocument();
|
|
67
73
|
});
|
|
68
74
|
|
|
69
|
-
test("
|
|
75
|
+
test("service and attribute filters stay behind the toggle", async () => {
|
|
70
76
|
renderForm();
|
|
71
77
|
|
|
72
78
|
await screen.findByText("Event Class");
|
|
73
79
|
|
|
74
|
-
expect(screen.queryByText("Event Severity")).not.toBeInTheDocument();
|
|
75
80
|
expect(
|
|
76
81
|
screen.queryByText("Filter by Telemetry Service"),
|
|
77
82
|
).not.toBeInTheDocument();
|
|
@@ -79,28 +84,83 @@ describe("SecurityEventsMonitorStepForm field gating", () => {
|
|
|
79
84
|
|
|
80
85
|
fireEvent.click(screen.getByText("Show Advanced Options"));
|
|
81
86
|
|
|
82
|
-
expect(screen.getByText("Event Severity")).toBeInTheDocument();
|
|
83
87
|
expect(screen.getByText("Filter by Telemetry Service")).toBeInTheDocument();
|
|
84
88
|
expect(screen.getByText("Filter by Attributes")).toBeInTheDocument();
|
|
85
89
|
});
|
|
86
90
|
|
|
87
|
-
test("a stored severity filter
|
|
91
|
+
test("a stored severity filter alone no longer forces the advanced section open", async () => {
|
|
88
92
|
/*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
93
|
+
* severityNames left the auto-open heuristic together with the
|
|
94
|
+
* toggle: the field is always on screen now, so a monitor that only
|
|
95
|
+
* filters by severity has nothing hidden worth revealing.
|
|
92
96
|
*/
|
|
93
97
|
renderForm({ severityNames: ["High" as never] });
|
|
94
98
|
|
|
95
99
|
expect(await screen.findByText("Event Severity")).toBeInTheDocument();
|
|
96
|
-
expect(
|
|
100
|
+
expect(
|
|
101
|
+
screen.queryByText("Filter by Telemetry Service"),
|
|
102
|
+
).not.toBeInTheDocument();
|
|
103
|
+
expect(screen.getByText("Show Advanced Options")).toBeInTheDocument();
|
|
97
104
|
});
|
|
98
105
|
|
|
99
|
-
test("a stored class filter alone
|
|
106
|
+
test("a stored class filter alone does not force the advanced section open", async () => {
|
|
100
107
|
renderForm({ classNames: ["Detection Finding"] });
|
|
101
108
|
|
|
102
109
|
expect(await screen.findByText("Event Class")).toBeInTheDocument();
|
|
103
|
-
expect(
|
|
110
|
+
expect(
|
|
111
|
+
screen.queryByText("Filter by Telemetry Service"),
|
|
112
|
+
).not.toBeInTheDocument();
|
|
104
113
|
expect(screen.getByText("Show Advanced Options")).toBeInTheDocument();
|
|
105
114
|
});
|
|
115
|
+
|
|
116
|
+
test("a stored telemetry-service filter still opens the advanced section by itself", async () => {
|
|
117
|
+
/*
|
|
118
|
+
* Editing a monitor whose config uses a filter that IS still
|
|
119
|
+
* advanced must show that filter immediately — the auto-open
|
|
120
|
+
* behaviour severityNames used to share before it stopped being
|
|
121
|
+
* advanced.
|
|
122
|
+
*/
|
|
123
|
+
renderForm({ telemetryServiceIds: [TELEMETRY_SERVICE_ID] });
|
|
124
|
+
|
|
125
|
+
expect(
|
|
126
|
+
await screen.findByText("Filter by Telemetry Service"),
|
|
127
|
+
).toBeInTheDocument();
|
|
128
|
+
expect(screen.getByText("Hide Advanced Options")).toBeInTheDocument();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("a stored attribute filter still opens the advanced section by itself", async () => {
|
|
132
|
+
renderForm({ attributes: { "user.name": "root" } });
|
|
133
|
+
|
|
134
|
+
expect(await screen.findByText("Filter by Attributes")).toBeInTheDocument();
|
|
135
|
+
expect(screen.getByText("Hide Advanced Options")).toBeInTheDocument();
|
|
136
|
+
|
|
137
|
+
/*
|
|
138
|
+
* The stored entry hydrates a dictionary row, and that row must
|
|
139
|
+
* carry the operator dropdown — the same operator restore the
|
|
140
|
+
* Log/Trace monitors rely on.
|
|
141
|
+
*/
|
|
142
|
+
expect(screen.getByText("Operator")).toBeInTheDocument();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("the attributes filter offers an operator on every new entry", async () => {
|
|
146
|
+
/*
|
|
147
|
+
* dictionaryEnableOperators is the other half of #3398: without it
|
|
148
|
+
* the dictionary renders a fixed "=" between key and value; with it
|
|
149
|
+
* each row gets an "Operator" dropdown (contains, is any of, ...).
|
|
150
|
+
*/
|
|
151
|
+
renderForm();
|
|
152
|
+
|
|
153
|
+
await screen.findByText("Event Class");
|
|
154
|
+
|
|
155
|
+
fireEvent.click(screen.getByText("Show Advanced Options"));
|
|
156
|
+
|
|
157
|
+
// No rows yet, so no per-row controls either.
|
|
158
|
+
expect(screen.queryByText("Operator")).not.toBeInTheDocument();
|
|
159
|
+
|
|
160
|
+
fireEvent.click(screen.getByText("Add Filter by Attributes"));
|
|
161
|
+
|
|
162
|
+
expect(screen.getByText("Operator")).toBeInTheDocument();
|
|
163
|
+
expect(screen.getByText("Key")).toBeInTheDocument();
|
|
164
|
+
expect(screen.getByText("Value")).toBeInTheDocument();
|
|
165
|
+
});
|
|
106
166
|
});
|