@oneuptime/common 12.0.31 → 12.0.33
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/AnalyticsModels/Span.ts +14 -0
- package/Models/DatabaseModels/AlertState.ts +0 -2
- package/Models/DatabaseModels/Domain.ts +1 -1
- package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
- package/Models/DatabaseModels/Incident.ts +1 -1
- package/Models/DatabaseModels/IncidentTemplate.ts +1 -1
- package/Models/DatabaseModels/Index.ts +12 -0
- package/Models/DatabaseModels/MetricType.ts +0 -2
- package/Models/DatabaseModels/Monitor.ts +76 -0
- package/Models/DatabaseModels/MonitorStatusTimeline.ts +0 -2
- package/Models/DatabaseModels/MonitorTest.ts +0 -2
- package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
- package/Models/DatabaseModels/NetworkDevice.ts +297 -3
- package/Models/DatabaseModels/NetworkDeviceOidTemplate.ts +3 -1
- package/Models/DatabaseModels/NetworkDeviceRole.ts +648 -0
- package/Models/DatabaseModels/NetworkSite.ts +201 -2
- package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
- package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -1
- package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +1 -1
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +0 -2
- package/Models/DatabaseModels/StatusPageAnnouncementTemplate.ts +0 -2
- package/Models/DatabaseModels/StatusPagePrivateUser.ts +0 -2
- package/Models/DatabaseModels/StatusPageResource.ts +0 -2
- package/Models/DatabaseModels/StatusPageSubscriber.ts +0 -2
- package/Models/DatabaseModels/TelemetryException.ts +119 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
- package/Server/API/EnterpriseLicenseAPI.ts +391 -64
- package/Server/API/LlmProviderAPI.ts +137 -22
- package/Server/EnvironmentConfig.ts +14 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.ts +72 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
- package/Server/Infrastructure/QueueWorker.ts +38 -8
- package/Server/Middleware/BearerTokenAuthorization.ts +12 -0
- package/Server/Middleware/ProjectAuthorization.ts +11 -0
- package/Server/Middleware/SCIMAuthorization.ts +12 -0
- package/Server/Middleware/TelemetryIngest.ts +11 -0
- package/Server/Services/AIBillingService.ts +101 -27
- package/Server/Services/DatabaseService.ts +39 -9
- package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
- package/Server/Services/EnterpriseLicenseService.ts +55 -0
- package/Server/Services/Index.ts +12 -0
- package/Server/Services/MonitorService.ts +143 -21
- package/Server/Services/MonitorStatusTimelineService.ts +150 -8
- package/Server/Services/MonitorTemplateService.ts +217 -1
- package/Server/Services/NetworkAlertPolicyEngineService.ts +2159 -0
- package/Server/Services/NetworkAlertPolicyService.ts +944 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +9 -10
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
- package/Server/Services/NetworkDeviceRoleService.ts +90 -0
- package/Server/Services/NetworkDeviceService.ts +1032 -73
- package/Server/Services/NetworkSiteService.ts +1502 -129
- package/Server/Services/NetworkSiteTypeService.ts +1216 -0
- package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
- package/Server/Services/NotificationService.ts +118 -28
- package/Server/Services/ProjectService.ts +186 -44
- package/Server/Services/StatusPagePrivateUserService.ts +103 -3
- package/Server/Services/UserNotificationEmailRollupBatchService.ts +78 -0
- package/Server/Services/UserNotificationEmailRollupItemService.ts +79 -0
- package/Server/Services/UserNotificationEmailRollupSettingService.ts +113 -0
- package/Server/Services/UserNotificationSettingService.ts +62 -31
- package/Server/Services/UserService.ts +95 -0
- package/Server/Types/Database/QueryHelper.ts +2 -2
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +14 -3
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +10 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +10 -0
- package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +62 -1
- package/Server/Utils/AI/Toolbox/AlertTools.ts +15 -1
- package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
- package/Server/Utils/DataSource/HttpFetch.ts +9 -2
- package/Server/Utils/EmailRollup/EmailRollupConstants.ts +98 -0
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +872 -0
- package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
- package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
- package/Server/Utils/LLM/LLMService.ts +78 -0
- package/Server/Utils/LogRedaction.ts +8 -0
- package/Server/Utils/Logger.ts +79 -1
- package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
- package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +49 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +43 -0
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +499 -19
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +66 -10
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +238 -44
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +146 -39
- package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +31 -18
- package/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.ts +213 -0
- package/Server/Utils/OutboundUserAgent.ts +152 -0
- package/Server/Utils/StartServer.ts +51 -19
- package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
- package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
- package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
- package/Server/Utils/Telemetry.ts +198 -51
- package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
- package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +158 -27
- package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
- package/Tests/App/Dashboard/DashboardChartWidgetZoom.test.tsx +35 -8
- package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +107 -3
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
- package/Tests/App/Dashboard/DashboardWideChartZoom.test.tsx +401 -0
- package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +18 -9
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
- package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
- package/Tests/App/Dashboard/MonitorTemplateColumnAndFacet.test.tsx +318 -0
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
- package/Tests/App/Dashboard/NetworkDeviceBulkDelete.test.tsx +357 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
- package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
- package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
- package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +626 -0
- package/Tests/App/Dashboard/PingMonitorProvisioning.test.ts +368 -0
- package/Tests/App/Dashboard/RecommendationCard.test.tsx +796 -0
- package/Tests/App/Dashboard/RecommendationToolbar.test.tsx +519 -0
- package/Tests/App/Dashboard/RecommendationsList.test.tsx +661 -0
- package/Tests/App/Dashboard/SideMenuHarness.tsx +11 -3
- package/Tests/App/Dashboard/UseBulkCreatePingMonitors.test.tsx +899 -0
- package/Tests/App/Dashboard/UseBulkSnmpCredentialProfileActions.test.tsx +732 -0
- package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +256 -0
- package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +11 -1
- package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
- package/Tests/Models/DatabaseModels/ModelRegistryInvariants.test.ts +115 -41
- package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
- package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
- package/Tests/Server/Infrastructure/Postgres/NetworkDeviceRoleTableMigration.test.ts +476 -0
- package/Tests/Server/Infrastructure/Postgres/NetworkSnmpCredentialProfilesAndAlertPoliciesMigration.test.ts +854 -0
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +18 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
- package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
- package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
- package/Tests/Server/Services/DatabaseServiceGenerateSlug.test.ts +215 -0
- package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
- package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
- package/Tests/Server/Services/MonitorServiceDeleteNetworkDeviceCleanup.test.ts +294 -0
- package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +802 -0
- package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +72 -2
- package/Tests/Server/Services/NetworkAlertPolicyEngineHooks.test.ts +752 -0
- package/Tests/Server/Services/NetworkAlertPolicyEngineService.test.ts +1849 -0
- package/Tests/Server/Services/NetworkAlertPolicyModel.test.ts +1793 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +47 -4
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
- package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
- package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
- package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
- package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
- package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
- package/Tests/Server/Services/NetworkDeviceRoleModel.test.ts +672 -0
- package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +1 -1
- package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
- package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
- package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
- package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
- package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
- package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +67 -4
- package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
- package/Tests/Server/Services/ScheduledMaintenanceSubscriberEndTime.test.ts +369 -0
- package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
- package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
- package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
- package/Tests/Server/Services/UserNotificationSettingMonitorDefaults.test.ts +248 -0
- package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +856 -0
- package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +145 -3
- package/Tests/Server/Types/Database/Permissions/DashboardAccessPermission.test.ts +321 -0
- package/Tests/Server/Types/Database/QueryHelperOperators.test.ts +17 -0
- package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +124 -0
- package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +208 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +235 -0
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +253 -0
- package/Tests/Server/Utils/BasicCron.test.ts +283 -0
- package/Tests/Server/Utils/Captcha.test.ts +422 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +96 -2
- package/Tests/Server/Utils/Database/MigrationFailureLog.test.ts +466 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1096 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerClaim.test.ts +466 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +752 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
- package/Tests/Server/Utils/IncomingCallPhoneNumber.test.ts +174 -0
- package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
- package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
- package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +196 -0
- package/Tests/Server/Utils/Monitor/DatabaseMetricWrite.test.ts +367 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +100 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +5 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +512 -31
- package/Tests/Server/Utils/Monitor/NetworkDeviceMetricUtil.test.ts +252 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +479 -42
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +351 -5
- package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +136 -12
- package/Tests/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.test.ts +306 -0
- package/Tests/Server/Utils/OutboundUserAgent.test.ts +266 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
- package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
- package/Tests/Server/Utils/Telemetry.test.ts +456 -66
- package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
- package/Tests/Types/Monitor/MonitorStepDatabaseMonitor.test.ts +243 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +16 -7
- package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +60 -0
- package/Tests/Types/NetworkDevice/DefaultNetworkDeviceRole.test.ts +417 -0
- package/Tests/Types/NetworkDevice/NetworkAlertPolicyScope.test.ts +655 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +115 -26
- package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +39 -0
- package/Tests/Types/NotificationSetting/NotificationEmailRollupPolicy.test.ts +299 -0
- package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
- package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
- package/Tests/UI/Components/Charts/ChartClickDoubleClickDisambiguation.test.tsx +221 -0
- package/Tests/UI/Components/Charts/ChartDoubleClickReset.test.tsx +220 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +751 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +475 -43
- package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +89 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
- package/Tests/UI/Components/NavBarCommandKGating.test.tsx +103 -8
- package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
- package/Tests/UI/Components/SideMenuItem.test.tsx +256 -4
- package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
- package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
- package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
- package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
- package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
- package/Tests/UI/Utils/TableColumnsToCsv.test.ts +30 -0
- package/Tests/UI/Utils/UseDashboardTimeRangeZoom.test.tsx +187 -0
- package/Tests/Utils/Dashboard/DashboardResourceListSharedArgs.test.ts +302 -0
- package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +242 -0
- package/Tests/Utils/EnterpriseLicenseSeats.test.ts +69 -0
- package/Tests/Utils/EnterpriseLicenseSync.test.ts +7 -1
- package/Tests/Utils/EnterpriseLicenseUsage.test.ts +433 -2
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
- package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
- package/Tests/Utils/Monitor/NetworkDeviceRoleCatalog.test.ts +981 -0
- package/Tests/Utils/Monitor/NetworkTopologyRoleCatalog.test.ts +865 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
- package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
- package/Tests/Utils/NetworkDevice/DeviceRoleKeyUtil.test.ts +538 -0
- package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
- package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
- package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
- package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
- package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
- package/Tests/Utils/NetworkDiscovery/PingMonitorBuilderForAddress.test.ts +274 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +230 -51
- package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +209 -0
- package/Tests/Utils/Slo/SloEvaluation.test.ts +171 -0
- package/Tests/Utils/Slug.test.ts +61 -1
- package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
- package/Tests/jest.setup.ts +19 -0
- package/Types/AI/ExceptionAIClassification.ts +10 -24
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +5 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.ts +13 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.ts +6 -0
- package/Types/Exception/ApiException.ts +10 -0
- package/Types/Exception/BadDataException.ts +11 -0
- package/Types/Exception/BadRequestException.ts +11 -0
- package/Types/Exception/Exception.ts +65 -0
- package/Types/Exception/ForbiddenException.ts +10 -0
- package/Types/Exception/NotAuthenticatedException.ts +10 -0
- package/Types/Exception/NotAuthorizedException.ts +10 -0
- package/Types/Exception/NotFoundException.ts +11 -0
- package/Types/Exception/PayloadTooLargeException.ts +11 -0
- package/Types/Exception/PaymentRequiredException.ts +10 -0
- package/Types/Exception/ServiceUnavailableException.ts +10 -0
- package/Types/Exception/SsoAuthorizationException.ts +10 -0
- package/Types/Exception/TenantNotFoundException.ts +11 -0
- package/Types/Exception/TimeoutException.ts +10 -0
- package/Types/Exception/TooManyRequestsException.ts +10 -0
- package/Types/Exception/UnableToReachServer.ts +10 -0
- package/Types/Exception/WebsiteRequestException.ts +10 -0
- package/Types/Monitor/CriteriaFilter.ts +60 -2
- package/Types/Monitor/DatabaseMetricCatalog.ts +693 -0
- package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +83 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +76 -0
- package/Types/Monitor/MonitorMetricType.ts +71 -0
- package/Types/Monitor/MonitorStep.ts +76 -0
- package/Types/Monitor/MonitorStepDatabaseMonitor.ts +171 -0
- package/Types/Monitor/MonitorStepSqlMonitor.ts +2 -20
- package/Types/Monitor/MonitorType.ts +47 -1
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +61 -0
- package/Types/Monitor/SqlConnectionConfig.ts +31 -0
- package/Types/NetworkDevice/DefaultNetworkDeviceRole.ts +145 -0
- package/Types/NetworkDevice/NetworkAlertPolicyScope.ts +343 -0
- package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +42 -22
- package/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.ts +30 -0
- package/Types/NotificationSetting/NotificationEmailRollupCategory.ts +255 -0
- package/Types/NotificationSetting/NotificationEmailRollupPolicy.ts +104 -0
- package/Types/Permission.ts +135 -0
- package/Types/Probe/ProbeMonitorResponse.ts +16 -0
- package/Types/Telemetry/ErrorClass.ts +274 -0
- package/Types/Telemetry/UnitOfWork.ts +59 -0
- package/UI/Components/Charts/Area/AreaChart.tsx +7 -0
- package/UI/Components/Charts/Bar/BarChart.tsx +6 -0
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +9 -1
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +97 -35
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +14 -0
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +97 -35
- package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +13 -0
- package/UI/Components/Charts/Line/LineChart.tsx +7 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
- package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
- package/UI/Components/Modal/Modal.tsx +2 -8
- package/UI/Components/ModelTable/BaseModelTable.tsx +50 -15
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
- package/UI/Components/Navbar/NavBar.tsx +62 -13
- package/UI/Components/Navbar/NavBarMenuModal.tsx +7 -2
- package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
- package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
- package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +2 -0
- package/UI/Components/SideMenu/SideMenu.tsx +135 -7
- package/UI/Components/SideMenu/SideMenuItem.tsx +80 -85
- package/UI/Components/SideMenu/SideMenuSection.tsx +69 -25
- package/UI/Components/SideOver/SideOver.tsx +21 -20
- package/UI/Utils/PageScrollLock.ts +79 -3
- package/UI/Utils/PermissionGate.ts +61 -0
- package/UI/Utils/SensitiveUrlToken.ts +112 -0
- package/UI/Utils/TestLLMProvider.ts +11 -0
- package/UI/Utils/UseDashboardTimeRangeZoom.ts +77 -0
- package/Utils/Dashboard/DashboardTimeRangeZoom.ts +118 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
- package/Utils/Monitor/MonitorMetricType.ts +153 -1
- package/Utils/Monitor/NetworkDeviceRoleCatalog.ts +232 -0
- package/Utils/Monitor/NetworkDeviceRoleUtil.ts +2 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +139 -36
- package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
- package/Utils/NetworkDevice/DeviceRoleKeyUtil.ts +137 -0
- package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
- package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
- package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
- package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
- package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
- package/Utils/Rules/RulePatternMatchUtil.ts +1 -1
- package/Utils/Slug.ts +34 -1
- package/build/dist/Models/AnalyticsModels/Span.js +14 -0
- package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertState.js +0 -2
- package/build/dist/Models/DatabaseModels/AlertState.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Domain.js +1 -1
- package/build/dist/Models/DatabaseModels/Domain.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +59 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +12 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MetricType.js +0 -2
- package/build/dist/Models/DatabaseModels/MetricType.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +75 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +0 -2
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorTest.js +0 -2
- package/build/dist/Models/DatabaseModels/MonitorTest.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +304 -4
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js +3 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceRole.js +677 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceRole.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncementTemplate.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncementTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageResource.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +123 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js +363 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +402 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js +296 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +273 -60
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
- package/build/dist/Server/API/LlmProviderAPI.js +108 -13
- package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +12 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.js +39 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/QueueWorker.js +33 -5
- package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
- package/build/dist/Server/Middleware/BearerTokenAuthorization.js +12 -0
- package/build/dist/Server/Middleware/BearerTokenAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/ProjectAuthorization.js +11 -0
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/SCIMAuthorization.js +12 -0
- package/build/dist/Server/Middleware/SCIMAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +11 -0
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIBillingService.js +70 -16
- package/build/dist/Server/Services/AIBillingService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +31 -5
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +167 -0
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +39 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +12 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +119 -21
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +127 -8
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +162 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js +1683 -0
- package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkAlertPolicyService.js +732 -0
- package/build/dist/Server/Services/NetworkAlertPolicyService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +10 -9
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceRoleService.js +70 -0
- package/build/dist/Server/Services/NetworkDeviceRoleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
- package/build/dist/Server/Services/NotificationService.js +80 -17
- package/build/dist/Server/Services/NotificationService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +131 -30
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +92 -2
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js +76 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js +77 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js +111 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js +46 -21
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +90 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +14 -3
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +10 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +10 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +54 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +18 -4
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js +59 -0
- package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +2 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +91 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +691 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +497 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +257 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -0
- package/build/dist/Server/Utils/LLM/LLMService.js +64 -1
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +8 -0
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
- package/build/dist/Server/Utils/Logger.js +63 -1
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js +141 -0
- package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +51 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +7 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +37 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +158 -6
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +32 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +330 -21
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +55 -10
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +178 -49
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +119 -29
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +30 -17
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -1
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js +158 -0
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js.map +1 -0
- package/build/dist/Server/Utils/OutboundUserAgent.js +123 -0
- package/build/dist/Server/Utils/OutboundUserAgent.js.map +1 -0
- package/build/dist/Server/Utils/StartServer.js +38 -14
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +28 -8
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js +95 -0
- package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/SpanUtil.js +29 -0
- package/build/dist/Server/Utils/Telemetry/SpanUtil.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry.js +162 -46
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Types/AI/ExceptionAIClassification.js +10 -24
- package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js +2 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js.map +1 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js +7 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js.map +1 -0
- package/build/dist/Types/Exception/ApiException.js +9 -0
- package/build/dist/Types/Exception/ApiException.js.map +1 -1
- package/build/dist/Types/Exception/BadDataException.js +10 -0
- package/build/dist/Types/Exception/BadDataException.js.map +1 -1
- package/build/dist/Types/Exception/BadRequestException.js +10 -0
- package/build/dist/Types/Exception/BadRequestException.js.map +1 -1
- package/build/dist/Types/Exception/Exception.js +56 -0
- package/build/dist/Types/Exception/Exception.js.map +1 -1
- package/build/dist/Types/Exception/ForbiddenException.js +9 -0
- package/build/dist/Types/Exception/ForbiddenException.js.map +1 -1
- package/build/dist/Types/Exception/NotAuthenticatedException.js +9 -0
- package/build/dist/Types/Exception/NotAuthenticatedException.js.map +1 -1
- package/build/dist/Types/Exception/NotAuthorizedException.js +9 -0
- package/build/dist/Types/Exception/NotAuthorizedException.js.map +1 -1
- package/build/dist/Types/Exception/NotFoundException.js +10 -0
- package/build/dist/Types/Exception/NotFoundException.js.map +1 -1
- package/build/dist/Types/Exception/PayloadTooLargeException.js +10 -0
- package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -1
- package/build/dist/Types/Exception/PaymentRequiredException.js +9 -0
- package/build/dist/Types/Exception/PaymentRequiredException.js.map +1 -1
- package/build/dist/Types/Exception/ServiceUnavailableException.js +9 -0
- package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -1
- package/build/dist/Types/Exception/SsoAuthorizationException.js +9 -0
- package/build/dist/Types/Exception/SsoAuthorizationException.js.map +1 -1
- package/build/dist/Types/Exception/TenantNotFoundException.js +10 -0
- package/build/dist/Types/Exception/TenantNotFoundException.js.map +1 -1
- package/build/dist/Types/Exception/TimeoutException.js +9 -0
- package/build/dist/Types/Exception/TimeoutException.js.map +1 -1
- package/build/dist/Types/Exception/TooManyRequestsException.js +9 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -1
- package/build/dist/Types/Exception/UnableToReachServer.js +9 -0
- package/build/dist/Types/Exception/UnableToReachServer.js.map +1 -1
- package/build/dist/Types/Exception/WebsiteRequestException.js +9 -0
- package/build/dist/Types/Exception/WebsiteRequestException.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +45 -2
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DatabaseMetricCatalog.js +594 -0
- package/build/dist/Types/Monitor/DatabaseMetricCatalog.js.map +1 -0
- package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js +21 -0
- package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +70 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorMetricType.js +61 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +54 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js +122 -0
- package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +45 -1
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +21 -1
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
- package/build/dist/Types/Monitor/SqlConnectionConfig.js +2 -0
- package/build/dist/Types/Monitor/SqlConnectionConfig.js.map +1 -0
- package/build/dist/Types/NetworkDevice/DefaultNetworkDeviceRole.js +105 -0
- package/build/dist/Types/NetworkDevice/DefaultNetworkDeviceRole.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js +172 -0
- package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +40 -22
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -1
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js +26 -0
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js +186 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js +87 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js.map +1 -0
- package/build/dist/Types/Permission.js +120 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
- package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
- package/build/dist/Types/Telemetry/UnitOfWork.js +59 -0
- package/build/dist/Types/Telemetry/UnitOfWork.js.map +1 -0
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +1 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +6 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +79 -31
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +7 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +79 -31
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +14 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -0
- package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +2 -7
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +3 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +2 -7
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +39 -13
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +39 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +44 -9
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -2
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js +12 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +1 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +76 -11
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js +50 -54
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js +32 -9
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Utils/PageScrollLock.js +31 -3
- package/build/dist/UI/Utils/PageScrollLock.js.map +1 -1
- package/build/dist/UI/Utils/PermissionGate.js +42 -1
- package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
- package/build/dist/UI/Utils/SensitiveUrlToken.js +97 -0
- package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -0
- package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
- package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
- package/build/dist/UI/Utils/UseDashboardTimeRangeZoom.js +42 -0
- package/build/dist/UI/Utils/UseDashboardTimeRangeZoom.js.map +1 -0
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +74 -0
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -0
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkDeviceRoleCatalog.js +126 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleCatalog.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js +2 -1
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +75 -35
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceRoleKeyUtil.js +114 -0
- package/build/dist/Utils/NetworkDevice/DeviceRoleKeyUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +85 -13
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +30 -15
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +191 -0
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -0
- package/build/dist/Utils/Rules/RulePatternMatchUtil.js +1 -1
- package/build/dist/Utils/Slug.js +31 -1
- package/build/dist/Utils/Slug.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,796 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import {
|
|
3
|
+
RenderResult,
|
|
4
|
+
fireEvent,
|
|
5
|
+
render,
|
|
6
|
+
screen,
|
|
7
|
+
} from "@testing-library/react";
|
|
8
|
+
import React from "react";
|
|
9
|
+
import { afterEach, describe, expect, jest, test } from "@jest/globals";
|
|
10
|
+
import RecommendationCard, {
|
|
11
|
+
DESCRIPTION_CLAMP_CHARACTER_COUNT,
|
|
12
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Components/Recommendations/RecommendationCard";
|
|
13
|
+
import {
|
|
14
|
+
RecommendationStatus,
|
|
15
|
+
RecommendationViewModel,
|
|
16
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Components/Recommendations/RecommendationViewModel";
|
|
17
|
+
import {
|
|
18
|
+
MonitorRecommendation,
|
|
19
|
+
MonitorRecommendationResourceType,
|
|
20
|
+
MonitorRecommendationSeverity,
|
|
21
|
+
} from "../../../Types/Monitor/Recommendation/MonitorRecommendationTypes";
|
|
22
|
+
import MonitorStep from "../../../Types/Monitor/MonitorStep";
|
|
23
|
+
import MonitorType from "../../../Types/Monitor/MonitorType";
|
|
24
|
+
import RecommendationType from "../../../Types/Recommendation/RecommendationType";
|
|
25
|
+
import Route from "../../../Types/API/Route";
|
|
26
|
+
import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
* One recommendation, in whichever of its three states it is in. The
|
|
30
|
+
* recommendations page renders up to eighteen of these at once, so every
|
|
31
|
+
* affordance on the card is repeated eighteen times and every mistake is too.
|
|
32
|
+
*
|
|
33
|
+
* These assertions are the ergonomics of that card, and each one stands in for
|
|
34
|
+
* something a user could not do before:
|
|
35
|
+
*
|
|
36
|
+
* - only the 16px checkbox was clickable, while the title and the paragraph
|
|
37
|
+
* beside it looked clickable and were not;
|
|
38
|
+
* - that checkbox was then a second tab stop and a second announcement for
|
|
39
|
+
* one action;
|
|
40
|
+
* - cards in a grid row share a height, so the single longest description in
|
|
41
|
+
* a category set the height of every short card beside it;
|
|
42
|
+
* - severity was carried by colour alone.
|
|
43
|
+
*
|
|
44
|
+
* The three states are the same object at different points in its life, so
|
|
45
|
+
* most of what follows is asserted against all three: what changes between
|
|
46
|
+
* them is which affordance the card offers, and offering the wrong one (a
|
|
47
|
+
* dismiss on a created card, a select while a batch is mid-flight) is how a
|
|
48
|
+
* user acts on something that is not there.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
const RECOMMENDATION_ID: string = "Kubernetes:k8s-node-not-ready";
|
|
52
|
+
const RECOMMENDATION_NAME: string = "Node Not Ready";
|
|
53
|
+
const SHORT_DESCRIPTION: string =
|
|
54
|
+
"Alert when a Kubernetes node stops reporting Ready.";
|
|
55
|
+
const DISMISSAL_REASON: string =
|
|
56
|
+
"We already page on the cloud provider's own node health check.";
|
|
57
|
+
|
|
58
|
+
const MONITOR_ROUTE: Route = new Route(
|
|
59
|
+
"/dashboard/6019bf0b1e0a2c1b5c8b4567/monitors/6019bf0b1e0a2c1b5c8b0001",
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
/*
|
|
63
|
+
* Descriptions built from the exported constant rather than hand-counted, so
|
|
64
|
+
* that changing the clamp threshold moves both fixtures with it instead of
|
|
65
|
+
* quietly turning the boundary cases into two long descriptions.
|
|
66
|
+
*/
|
|
67
|
+
type BuildDescriptionOfLengthFunction = (length: number) => string;
|
|
68
|
+
|
|
69
|
+
const buildDescriptionOfLength: BuildDescriptionOfLengthFunction = (
|
|
70
|
+
length: number,
|
|
71
|
+
): string => {
|
|
72
|
+
const filler: string = "the cgroup CFS quota throttles the container, ";
|
|
73
|
+
const text: string = `Fires when ${filler.repeat(10)}`;
|
|
74
|
+
|
|
75
|
+
return `${text.slice(0, length - 1)}.`;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const AT_CLAMP_LIMIT_DESCRIPTION: string = buildDescriptionOfLength(
|
|
79
|
+
DESCRIPTION_CLAMP_CHARACTER_COUNT,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const OVER_CLAMP_LIMIT_DESCRIPTION: string = buildDescriptionOfLength(
|
|
83
|
+
DESCRIPTION_CLAMP_CHARACTER_COUNT + 1,
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const onSelectChange: MockFunction = getJestMockFunction();
|
|
87
|
+
const onDismiss: MockFunction = getJestMockFunction();
|
|
88
|
+
const onRestore: MockFunction = getJestMockFunction();
|
|
89
|
+
|
|
90
|
+
interface ViewModelOptions {
|
|
91
|
+
status: RecommendationStatus;
|
|
92
|
+
name?: string | undefined;
|
|
93
|
+
description?: string | undefined;
|
|
94
|
+
severity?: MonitorRecommendationSeverity | undefined;
|
|
95
|
+
dismissalReason?: string | undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
type BuildViewModelFunction = (
|
|
99
|
+
options: ViewModelOptions,
|
|
100
|
+
) => RecommendationViewModel;
|
|
101
|
+
|
|
102
|
+
const buildViewModel: BuildViewModelFunction = (
|
|
103
|
+
options: ViewModelOptions,
|
|
104
|
+
): RecommendationViewModel => {
|
|
105
|
+
const recommendation: MonitorRecommendation = {
|
|
106
|
+
recommendationId: RECOMMENDATION_ID,
|
|
107
|
+
recommendationType: RecommendationType.Monitor,
|
|
108
|
+
resourceType: MonitorRecommendationResourceType.Kubernetes,
|
|
109
|
+
monitorType: MonitorType.Kubernetes,
|
|
110
|
+
templateId: "k8s-node-not-ready",
|
|
111
|
+
name: options.name || RECOMMENDATION_NAME,
|
|
112
|
+
description: options.description || SHORT_DESCRIPTION,
|
|
113
|
+
category: "Cluster Health",
|
|
114
|
+
severity: options.severity || "Critical",
|
|
115
|
+
/*
|
|
116
|
+
* The card must never build a monitor step: that happens in the create
|
|
117
|
+
* side-over, after the user has picked severities and on-call policies.
|
|
118
|
+
* Throwing turns "the card called it while merely rendering" into a
|
|
119
|
+
* failure here rather than into a wasted object nobody sees.
|
|
120
|
+
*/
|
|
121
|
+
getMonitorStep: (): MonitorStep => {
|
|
122
|
+
throw new Error("RecommendationCard must not build a monitor step.");
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
recommendation: recommendation,
|
|
128
|
+
status: options.status,
|
|
129
|
+
dismissalReason: options.dismissalReason,
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
interface CardOptions {
|
|
134
|
+
viewModel: RecommendationViewModel;
|
|
135
|
+
isSelected?: boolean | undefined;
|
|
136
|
+
isDisabled?: boolean | undefined;
|
|
137
|
+
monitorRoute?: Route | undefined;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
type RenderCardFunction = (options: CardOptions) => RenderResult;
|
|
141
|
+
|
|
142
|
+
const renderCard: RenderCardFunction = (options: CardOptions): RenderResult => {
|
|
143
|
+
return render(
|
|
144
|
+
<RecommendationCard
|
|
145
|
+
viewModel={options.viewModel}
|
|
146
|
+
isSelected={options.isSelected === true}
|
|
147
|
+
isDisabled={options.isDisabled}
|
|
148
|
+
monitorRoute={options.monitorRoute}
|
|
149
|
+
onSelectChange={onSelectChange}
|
|
150
|
+
onDismiss={onDismiss}
|
|
151
|
+
onRestore={onRestore}
|
|
152
|
+
/>,
|
|
153
|
+
);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
type QueryElementFunction = () => HTMLElement | null;
|
|
157
|
+
|
|
158
|
+
/*
|
|
159
|
+
* The page keeps its selection state keyed on recommendationId and addresses
|
|
160
|
+
* the card through this test id, so the id has to stay in it.
|
|
161
|
+
*/
|
|
162
|
+
const querySelectButton: QueryElementFunction = (): HTMLElement | null => {
|
|
163
|
+
return screen.queryByTestId(
|
|
164
|
+
`recommendation-card-select-${RECOMMENDATION_ID}`,
|
|
165
|
+
);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const queryDismissButton: QueryElementFunction = (): HTMLElement | null => {
|
|
169
|
+
return screen.queryByRole("button", {
|
|
170
|
+
name: `Dismiss ${RECOMMENDATION_NAME}`,
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const queryRestoreButton: QueryElementFunction = (): HTMLElement | null => {
|
|
175
|
+
return screen.queryByRole("button", { name: "Restore" });
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const queryDescriptionToggle: QueryElementFunction = (): HTMLElement | null => {
|
|
179
|
+
return screen.queryByTestId(
|
|
180
|
+
`recommendation-description-toggle-${RECOMMENDATION_ID}`,
|
|
181
|
+
);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
type GetElementFunction = () => HTMLElement;
|
|
185
|
+
|
|
186
|
+
const getSelectButton: GetElementFunction = (): HTMLElement => {
|
|
187
|
+
return screen.getByRole("button", { name: `Select ${RECOMMENDATION_NAME}` });
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const getDescription: GetElementFunction = (): HTMLElement => {
|
|
191
|
+
return screen.getByTestId(`recommendation-description-${RECOMMENDATION_ID}`);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
type IsDescriptionClampedFunction = () => boolean;
|
|
195
|
+
|
|
196
|
+
const isDescriptionClamped: IsDescriptionClampedFunction = (): boolean => {
|
|
197
|
+
return getDescription().className.includes("line-clamp-3");
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
type GetCheckboxInputFunction = (container: HTMLElement) => HTMLInputElement;
|
|
201
|
+
|
|
202
|
+
const getCheckboxInput: GetCheckboxInputFunction = (
|
|
203
|
+
container: HTMLElement,
|
|
204
|
+
): HTMLInputElement => {
|
|
205
|
+
const input: HTMLInputElement | null =
|
|
206
|
+
container.querySelector<HTMLInputElement>('input[type="checkbox"]');
|
|
207
|
+
|
|
208
|
+
if (!input) {
|
|
209
|
+
throw new Error("The card rendered no checkbox.");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return input;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/*
|
|
216
|
+
* The 2px severity edge. It is decorative — aria-hidden — which is precisely
|
|
217
|
+
* why the severity has to be readable somewhere else too.
|
|
218
|
+
*/
|
|
219
|
+
type GetSeverityRailClassFunction = (container: HTMLElement) => string;
|
|
220
|
+
|
|
221
|
+
const getSeverityRailClass: GetSeverityRailClassFunction = (
|
|
222
|
+
container: HTMLElement,
|
|
223
|
+
): string => {
|
|
224
|
+
const rail: Element | null = container.querySelector(
|
|
225
|
+
'div[aria-hidden="true"][class*="inset-y-0"]',
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
if (!rail) {
|
|
229
|
+
throw new Error("The card rendered no severity rail.");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return rail.className;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
describe("RecommendationCard", () => {
|
|
236
|
+
afterEach(() => {
|
|
237
|
+
jest.clearAllMocks();
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe("the three states", () => {
|
|
241
|
+
test("an available recommendation offers the select control and neither badge", () => {
|
|
242
|
+
renderCard({
|
|
243
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
expect(getSelectButton()).toBeInTheDocument();
|
|
247
|
+
expect(screen.getByText(RECOMMENDATION_NAME)).toBeInTheDocument();
|
|
248
|
+
expect(screen.queryByText("Created")).not.toBeInTheDocument();
|
|
249
|
+
expect(screen.queryByText("Dismissed")).not.toBeInTheDocument();
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
/*
|
|
253
|
+
* "Created" is the only thing separating a recommendation you still have
|
|
254
|
+
* to act on from one whose monitor is already running. Without it the
|
|
255
|
+
* page invites the user to create a second copy of a monitor they have.
|
|
256
|
+
*/
|
|
257
|
+
test("a created recommendation is badged Created and cannot be selected", () => {
|
|
258
|
+
renderCard({
|
|
259
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Created }),
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
expect(screen.getByText("Created")).toBeInTheDocument();
|
|
263
|
+
expect(querySelectButton()).not.toBeInTheDocument();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
/*
|
|
267
|
+
* The payoff for a created card: the monitor exists, so the card's job is
|
|
268
|
+
* to get the user to it. A created card with nowhere to go is a dead end.
|
|
269
|
+
*/
|
|
270
|
+
test("a created recommendation links to the monitor it produced", () => {
|
|
271
|
+
renderCard({
|
|
272
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Created }),
|
|
273
|
+
monitorRoute: MONITOR_ROUTE,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const link: HTMLElement = screen.getByRole("link", {
|
|
277
|
+
name: "View monitor",
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
expect(link).toBeInTheDocument();
|
|
281
|
+
expect(link).toHaveAttribute("href", MONITOR_ROUTE.toString());
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
/*
|
|
285
|
+
* The monitor id is resolved by a lookup that can come back empty. A link
|
|
286
|
+
* rendered anyway would point at /monitors/undefined.
|
|
287
|
+
*/
|
|
288
|
+
test("a created recommendation with no route renders no link", () => {
|
|
289
|
+
renderCard({
|
|
290
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Created }),
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
expect(screen.queryByRole("link")).not.toBeInTheDocument();
|
|
294
|
+
expect(screen.queryByText("View monitor")).not.toBeInTheDocument();
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test("a dismissed recommendation is badged Dismissed and shows its reason", () => {
|
|
298
|
+
renderCard({
|
|
299
|
+
viewModel: buildViewModel({
|
|
300
|
+
status: RecommendationStatus.Dismissed,
|
|
301
|
+
dismissalReason: DISMISSAL_REASON,
|
|
302
|
+
}),
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
expect(screen.getByText("Dismissed")).toBeInTheDocument();
|
|
306
|
+
expect(screen.getByText(DISMISSAL_REASON)).toBeInTheDocument();
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
/*
|
|
310
|
+
* The reason is what stops the next person re-litigating a decision the
|
|
311
|
+
* team already made, but it is optional on the dismissal row. When it is
|
|
312
|
+
* absent the card must render nothing rather than an empty quote box —
|
|
313
|
+
* a bordered, italic, empty strip reads as a rendering failure.
|
|
314
|
+
*/
|
|
315
|
+
test("a dismissed recommendation with no reason renders no empty reason box", () => {
|
|
316
|
+
const { container }: RenderResult = renderCard({
|
|
317
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Dismissed }),
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
expect(screen.getByText("Dismissed")).toBeInTheDocument();
|
|
321
|
+
expect(container.querySelectorAll("p")).toHaveLength(1);
|
|
322
|
+
expect(screen.getByText(SHORT_DESCRIPTION)).toBeInTheDocument();
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
test("a dismissed recommendation can be restored", () => {
|
|
326
|
+
renderCard({
|
|
327
|
+
viewModel: buildViewModel({
|
|
328
|
+
status: RecommendationStatus.Dismissed,
|
|
329
|
+
dismissalReason: DISMISSAL_REASON,
|
|
330
|
+
}),
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
const restoreButton: HTMLElement | null = queryRestoreButton();
|
|
334
|
+
|
|
335
|
+
expect(restoreButton).toBeInTheDocument();
|
|
336
|
+
|
|
337
|
+
fireEvent.click(restoreButton as HTMLElement);
|
|
338
|
+
|
|
339
|
+
expect(onRestore).toHaveBeenCalledTimes(1);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
test("available and created recommendations have nothing to restore", () => {
|
|
343
|
+
renderCard({
|
|
344
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
expect(queryRestoreButton()).not.toBeInTheDocument();
|
|
348
|
+
|
|
349
|
+
renderCard({
|
|
350
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Created }),
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
expect(queryRestoreButton()).not.toBeInTheDocument();
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
/*
|
|
358
|
+
* The whole card is the hit target, not the 16px box in its corner. This is
|
|
359
|
+
* the fix for the complaint that started this work: the title and the
|
|
360
|
+
* description look like part of the control and were not, so a click that
|
|
361
|
+
* landed a few pixels off did nothing at all and gave no feedback.
|
|
362
|
+
*/
|
|
363
|
+
describe("whole-card selection", () => {
|
|
364
|
+
test("the hit target is a real button that names the recommendation", () => {
|
|
365
|
+
renderCard({
|
|
366
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
const selectButton: HTMLElement = getSelectButton();
|
|
370
|
+
|
|
371
|
+
/*
|
|
372
|
+
* A div with an onClick would satisfy a click test and still be
|
|
373
|
+
* unreachable by keyboard, so the element type is the assertion.
|
|
374
|
+
*/
|
|
375
|
+
expect(selectButton.tagName).toBe("BUTTON");
|
|
376
|
+
expect(selectButton).toBe(querySelectButton());
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
test("aria-pressed reports the unselected state", () => {
|
|
380
|
+
renderCard({
|
|
381
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
382
|
+
isSelected: false,
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
expect(getSelectButton()).toHaveAttribute("aria-pressed", "false");
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
/*
|
|
389
|
+
* Selection drives a batch create of everything ticked, so a card whose
|
|
390
|
+
* pressed state does not match the page's selection set is a monitor the
|
|
391
|
+
* user did not ask for or one they did and will not get.
|
|
392
|
+
*/
|
|
393
|
+
test("aria-pressed reports the selected state", () => {
|
|
394
|
+
renderCard({
|
|
395
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
396
|
+
isSelected: true,
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
expect(getSelectButton()).toHaveAttribute("aria-pressed", "true");
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
test("clicking an unselected card asks to select it", () => {
|
|
403
|
+
renderCard({
|
|
404
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
405
|
+
isSelected: false,
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
fireEvent.click(getSelectButton());
|
|
409
|
+
|
|
410
|
+
expect(onSelectChange).toHaveBeenCalledTimes(1);
|
|
411
|
+
expect(onSelectChange).toHaveBeenCalledWith(true);
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
/*
|
|
415
|
+
* The other direction, because a card that only ever reports `true` looks
|
|
416
|
+
* correct until someone tries to take one recommendation back out of a
|
|
417
|
+
* selection of eighteen.
|
|
418
|
+
*/
|
|
419
|
+
test("clicking a selected card asks to deselect it", () => {
|
|
420
|
+
renderCard({
|
|
421
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
422
|
+
isSelected: true,
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
fireEvent.click(getSelectButton());
|
|
426
|
+
|
|
427
|
+
expect(onSelectChange).toHaveBeenCalledTimes(1);
|
|
428
|
+
expect(onSelectChange).toHaveBeenCalledWith(false);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
test("a dismissed card offers no selection", () => {
|
|
432
|
+
renderCard({
|
|
433
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Dismissed }),
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
expect(querySelectButton()).not.toBeInTheDocument();
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
/*
|
|
441
|
+
* Two controls for one action is two tab stops and two announcements. The
|
|
442
|
+
* visible box stays because it is what makes the card legible as selectable
|
|
443
|
+
* at a glance, but assistive technology must see only the card button.
|
|
444
|
+
*/
|
|
445
|
+
describe("the visible checkbox is presentational", () => {
|
|
446
|
+
test("it is not announced as a second control", () => {
|
|
447
|
+
renderCard({
|
|
448
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
expect(screen.queryByRole("checkbox")).not.toBeInTheDocument();
|
|
452
|
+
expect(
|
|
453
|
+
screen.getAllByRole("button", {
|
|
454
|
+
name: `Select ${RECOMMENDATION_NAME}`,
|
|
455
|
+
}),
|
|
456
|
+
).toHaveLength(1);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
test("it is not a second tab stop", () => {
|
|
460
|
+
const { container }: RenderResult = renderCard({
|
|
461
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
expect(getCheckboxInput(container).tabIndex).toBe(-1);
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
/*
|
|
468
|
+
* Presentational, not decorative: it is the only thing on the card that
|
|
469
|
+
* shows the selection at a glance, so it still has to be ticked.
|
|
470
|
+
*/
|
|
471
|
+
test("it still shows an unselected card as unticked", () => {
|
|
472
|
+
const { container }: RenderResult = renderCard({
|
|
473
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
474
|
+
isSelected: false,
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
expect(getCheckboxInput(container).checked).toBe(false);
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
test("it still shows a selected card as ticked", () => {
|
|
481
|
+
const { container }: RenderResult = renderCard({
|
|
482
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
483
|
+
isSelected: true,
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
expect(getCheckboxInput(container).checked).toBe(true);
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
/*
|
|
491
|
+
* isDisabled means a create batch is in flight. The selection it is working
|
|
492
|
+
* from was fixed when it started, so anything that would change that
|
|
493
|
+
* selection — or dismiss a recommendation out from under it — has to be
|
|
494
|
+
* gone, not merely styled as unavailable.
|
|
495
|
+
*/
|
|
496
|
+
describe("while a batch is running", () => {
|
|
497
|
+
test("an available card offers neither selection nor dismissal", () => {
|
|
498
|
+
renderCard({
|
|
499
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
500
|
+
isDisabled: true,
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
expect(querySelectButton()).not.toBeInTheDocument();
|
|
504
|
+
expect(queryDismissButton()).not.toBeInTheDocument();
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
test("the checkbox on a disabled card cannot be ticked", () => {
|
|
508
|
+
const { container }: RenderResult = renderCard({
|
|
509
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
510
|
+
isDisabled: true,
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
expect(getCheckboxInput(container).disabled).toBe(true);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
test("a dismissed card offers no restore", () => {
|
|
517
|
+
renderCard({
|
|
518
|
+
viewModel: buildViewModel({
|
|
519
|
+
status: RecommendationStatus.Dismissed,
|
|
520
|
+
dismissalReason: DISMISSAL_REASON,
|
|
521
|
+
}),
|
|
522
|
+
isDisabled: true,
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
expect(queryRestoreButton()).not.toBeInTheDocument();
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
/*
|
|
529
|
+
* Navigation is not a mutation. Hiding the link to a monitor that already
|
|
530
|
+
* exists because some other monitor is being created would be a
|
|
531
|
+
* disabled state that punishes the user for the page's own work.
|
|
532
|
+
*/
|
|
533
|
+
test("a created card still links to its monitor", () => {
|
|
534
|
+
renderCard({
|
|
535
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Created }),
|
|
536
|
+
monitorRoute: MONITOR_ROUTE,
|
|
537
|
+
isDisabled: true,
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
expect(
|
|
541
|
+
screen.getByRole("link", { name: "View monitor" }),
|
|
542
|
+
).toBeInTheDocument();
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
/*
|
|
547
|
+
* Dismiss is per-card and permanent enough to need naming: eighteen cards
|
|
548
|
+
* means eighteen close buttons, and "Dismiss" alone tells a screen reader
|
|
549
|
+
* user nothing about which of the eighteen they are on.
|
|
550
|
+
*/
|
|
551
|
+
describe("dismissal", () => {
|
|
552
|
+
test("an available card can be dismissed by name", () => {
|
|
553
|
+
renderCard({
|
|
554
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
const dismissButton: HTMLElement | null = queryDismissButton();
|
|
558
|
+
|
|
559
|
+
expect(dismissButton).toBeInTheDocument();
|
|
560
|
+
|
|
561
|
+
fireEvent.click(dismissButton as HTMLElement);
|
|
562
|
+
|
|
563
|
+
expect(onDismiss).toHaveBeenCalledTimes(1);
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
/*
|
|
567
|
+
* The dismiss control sits inside a card whose whole surface selects. If
|
|
568
|
+
* it ever ends up nested inside that button, dismissing would also tick
|
|
569
|
+
* the card and queue it for creation — the exact opposite of the intent.
|
|
570
|
+
*/
|
|
571
|
+
test("dismissing does not also select the card", () => {
|
|
572
|
+
renderCard({
|
|
573
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Available }),
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
fireEvent.click(queryDismissButton() as HTMLElement);
|
|
577
|
+
|
|
578
|
+
expect(onSelectChange).not.toHaveBeenCalled();
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
test("a created card cannot be dismissed", () => {
|
|
582
|
+
renderCard({
|
|
583
|
+
viewModel: buildViewModel({ status: RecommendationStatus.Created }),
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
expect(queryDismissButton()).not.toBeInTheDocument();
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
test("an already dismissed card cannot be dismissed again", () => {
|
|
590
|
+
renderCard({
|
|
591
|
+
viewModel: buildViewModel({
|
|
592
|
+
status: RecommendationStatus.Dismissed,
|
|
593
|
+
dismissalReason: DISMISSAL_REASON,
|
|
594
|
+
}),
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
expect(queryDismissButton()).not.toBeInTheDocument();
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
/*
|
|
602
|
+
* Cards in a grid row share a height. Before the clamp, one four-line
|
|
603
|
+
* explanation of CFS quota accounting set the height of every card beside
|
|
604
|
+
* it, leaving a hand's width of white space next to "Alert when Kubernetes
|
|
605
|
+
* jobs fail."
|
|
606
|
+
*/
|
|
607
|
+
describe("description clamping", () => {
|
|
608
|
+
/*
|
|
609
|
+
* The two fixtures are meant to sit either side of the threshold, one
|
|
610
|
+
* character apart. If the helper ever drifts, the tests below would still
|
|
611
|
+
* pass while testing two long descriptions.
|
|
612
|
+
*/
|
|
613
|
+
test("the fixtures straddle the clamp threshold by one character", () => {
|
|
614
|
+
expect(AT_CLAMP_LIMIT_DESCRIPTION).toHaveLength(
|
|
615
|
+
DESCRIPTION_CLAMP_CHARACTER_COUNT,
|
|
616
|
+
);
|
|
617
|
+
expect(OVER_CLAMP_LIMIT_DESCRIPTION).toHaveLength(
|
|
618
|
+
DESCRIPTION_CLAMP_CHARACTER_COUNT + 1,
|
|
619
|
+
);
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
/*
|
|
623
|
+
* A description exactly at the threshold fits, so a Show more beside it
|
|
624
|
+
* would be a control that reveals nothing.
|
|
625
|
+
*/
|
|
626
|
+
test("a description at the threshold is neither clamped nor toggleable", () => {
|
|
627
|
+
renderCard({
|
|
628
|
+
viewModel: buildViewModel({
|
|
629
|
+
status: RecommendationStatus.Available,
|
|
630
|
+
description: AT_CLAMP_LIMIT_DESCRIPTION,
|
|
631
|
+
}),
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
expect(queryDescriptionToggle()).not.toBeInTheDocument();
|
|
635
|
+
expect(
|
|
636
|
+
screen.queryByRole("button", { name: "Show more" }),
|
|
637
|
+
).not.toBeInTheDocument();
|
|
638
|
+
expect(isDescriptionClamped()).toBe(false);
|
|
639
|
+
expect(getDescription()).toHaveTextContent(AT_CLAMP_LIMIT_DESCRIPTION);
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
test("a longer description is clamped and offers Show more", () => {
|
|
643
|
+
renderCard({
|
|
644
|
+
viewModel: buildViewModel({
|
|
645
|
+
status: RecommendationStatus.Available,
|
|
646
|
+
description: OVER_CLAMP_LIMIT_DESCRIPTION,
|
|
647
|
+
}),
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
const toggle: HTMLElement = screen.getByRole("button", {
|
|
651
|
+
name: "Show more",
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
expect(toggle).toHaveAttribute("aria-expanded", "false");
|
|
655
|
+
expect(isDescriptionClamped()).toBe(true);
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
/*
|
|
659
|
+
* The clamp is three lines of CSS and nothing else. Every character stays
|
|
660
|
+
* in the DOM in both states, so a screen reader — which does not see the
|
|
661
|
+
* clamp at all — reads the whole description either way. A test that
|
|
662
|
+
* proved truncation by asserting the tail was absent would be asserting
|
|
663
|
+
* that content is hidden from assistive technology.
|
|
664
|
+
*/
|
|
665
|
+
test("the whole description is in the DOM while clamped", () => {
|
|
666
|
+
renderCard({
|
|
667
|
+
viewModel: buildViewModel({
|
|
668
|
+
status: RecommendationStatus.Available,
|
|
669
|
+
description: OVER_CLAMP_LIMIT_DESCRIPTION,
|
|
670
|
+
}),
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
expect(getDescription().textContent).toBe(OVER_CLAMP_LIMIT_DESCRIPTION);
|
|
674
|
+
expect(
|
|
675
|
+
screen.getByText(OVER_CLAMP_LIMIT_DESCRIPTION),
|
|
676
|
+
).toBeInTheDocument();
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
test("Show more unclamps the description and becomes Show less", () => {
|
|
680
|
+
renderCard({
|
|
681
|
+
viewModel: buildViewModel({
|
|
682
|
+
status: RecommendationStatus.Available,
|
|
683
|
+
description: OVER_CLAMP_LIMIT_DESCRIPTION,
|
|
684
|
+
}),
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
fireEvent.click(screen.getByRole("button", { name: "Show more" }));
|
|
688
|
+
|
|
689
|
+
const toggle: HTMLElement = screen.getByRole("button", {
|
|
690
|
+
name: "Show less",
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
expect(toggle).toHaveAttribute("aria-expanded", "true");
|
|
694
|
+
expect(isDescriptionClamped()).toBe(false);
|
|
695
|
+
expect(getDescription().textContent).toBe(OVER_CLAMP_LIMIT_DESCRIPTION);
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
/*
|
|
699
|
+
* Expanding is reversible, because a user who expands three cards to read
|
|
700
|
+
* them has no other way to get the row heights back.
|
|
701
|
+
*/
|
|
702
|
+
test("Show less clamps it again", () => {
|
|
703
|
+
renderCard({
|
|
704
|
+
viewModel: buildViewModel({
|
|
705
|
+
status: RecommendationStatus.Available,
|
|
706
|
+
description: OVER_CLAMP_LIMIT_DESCRIPTION,
|
|
707
|
+
}),
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
fireEvent.click(screen.getByRole("button", { name: "Show more" }));
|
|
711
|
+
fireEvent.click(screen.getByRole("button", { name: "Show less" }));
|
|
712
|
+
|
|
713
|
+
expect(screen.getByRole("button", { name: "Show more" })).toHaveAttribute(
|
|
714
|
+
"aria-expanded",
|
|
715
|
+
"false",
|
|
716
|
+
);
|
|
717
|
+
expect(isDescriptionClamped()).toBe(true);
|
|
718
|
+
expect(getDescription().textContent).toBe(OVER_CLAMP_LIMIT_DESCRIPTION);
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
/*
|
|
722
|
+
* Reading is not choosing. The toggle sits on top of a card whose whole
|
|
723
|
+
* surface selects, so if it ever ends up inside that button, expanding a
|
|
724
|
+
* description would queue a monitor for creation.
|
|
725
|
+
*/
|
|
726
|
+
test("expanding a description does not select the card", () => {
|
|
727
|
+
renderCard({
|
|
728
|
+
viewModel: buildViewModel({
|
|
729
|
+
status: RecommendationStatus.Available,
|
|
730
|
+
description: OVER_CLAMP_LIMIT_DESCRIPTION,
|
|
731
|
+
}),
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
fireEvent.click(screen.getByRole("button", { name: "Show more" }));
|
|
735
|
+
|
|
736
|
+
expect(onSelectChange).not.toHaveBeenCalled();
|
|
737
|
+
});
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
/*
|
|
741
|
+
* Severity is the one attribute you scan a list of eighteen for, so it is
|
|
742
|
+
* carried twice: a coloured edge for peripheral vision and a badge for
|
|
743
|
+
* everyone else. Colour alone is not an accessible signal (WCAG 1.4.1), and
|
|
744
|
+
* the edge is aria-hidden, so the badge is the only reading of severity a
|
|
745
|
+
* screen reader or a red-green colourblind user gets.
|
|
746
|
+
*/
|
|
747
|
+
describe("severity", () => {
|
|
748
|
+
test("a critical recommendation has a red rail and says Critical", () => {
|
|
749
|
+
const { container }: RenderResult = renderCard({
|
|
750
|
+
viewModel: buildViewModel({
|
|
751
|
+
status: RecommendationStatus.Available,
|
|
752
|
+
severity: "Critical",
|
|
753
|
+
}),
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
expect(getSeverityRailClass(container)).toContain("bg-red-400");
|
|
757
|
+
expect(screen.getByText("Critical")).toBeInTheDocument();
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
test("a warning recommendation has an amber rail and says Warning", () => {
|
|
761
|
+
const { container }: RenderResult = renderCard({
|
|
762
|
+
viewModel: buildViewModel({
|
|
763
|
+
status: RecommendationStatus.Available,
|
|
764
|
+
severity: "Warning",
|
|
765
|
+
}),
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
expect(getSeverityRailClass(container)).toContain("bg-amber-400");
|
|
769
|
+
expect(screen.getByText("Warning")).toBeInTheDocument();
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
/*
|
|
773
|
+
* The rail only earns its place if the two severities actually differ at
|
|
774
|
+
* a glance — one shared accent would be decoration, not information.
|
|
775
|
+
*/
|
|
776
|
+
test("the two severities do not share a rail colour", () => {
|
|
777
|
+
const critical: RenderResult = renderCard({
|
|
778
|
+
viewModel: buildViewModel({
|
|
779
|
+
status: RecommendationStatus.Available,
|
|
780
|
+
severity: "Critical",
|
|
781
|
+
}),
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
const warning: RenderResult = renderCard({
|
|
785
|
+
viewModel: buildViewModel({
|
|
786
|
+
status: RecommendationStatus.Available,
|
|
787
|
+
severity: "Warning",
|
|
788
|
+
}),
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
expect(getSeverityRailClass(critical.container)).not.toBe(
|
|
792
|
+
getSeverityRailClass(warning.container),
|
|
793
|
+
);
|
|
794
|
+
});
|
|
795
|
+
});
|
|
796
|
+
});
|