@oneuptime/common 12.0.22 → 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.
Files changed (345) hide show
  1. package/Models/DatabaseModels/DetectionRule.ts +55 -0
  2. package/Models/DatabaseModels/Index.ts +2 -0
  3. package/Models/DatabaseModels/NetworkDevice.ts +44 -0
  4. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +584 -0
  5. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +105 -0
  6. package/Models/DatabaseModels/Project.ts +68 -0
  7. package/Models/DatabaseModels/User.ts +68 -0
  8. package/Server/API/TelemetryAPI.ts +29 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.ts +60 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.ts +26 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.ts +26 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.ts +28 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.ts +49 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.ts +33 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
  16. package/Server/Middleware/GzipRequestBody.ts +311 -0
  17. package/Server/Middleware/MultipartFormData.ts +87 -3
  18. package/Server/Services/DetectionRuleService.ts +73 -6
  19. package/Server/Services/Index.ts +207 -0
  20. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +917 -0
  21. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +181 -0
  22. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +59 -0
  23. package/Server/Services/NetworkDeviceService.ts +148 -0
  24. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
  25. package/Server/Services/OnCallDutyPolicyFeedService.ts +1 -1
  26. package/Server/Services/ProjectService.ts +29 -19
  27. package/Server/Services/SecurityEventService.ts +90 -13
  28. package/Server/Services/StatusPageResourceService.ts +223 -0
  29. package/Server/Services/TelemetryAttributeService.ts +17 -0
  30. package/Server/Services/UserService.ts +4 -6
  31. package/Server/Types/Markdown.ts +161 -67
  32. package/Server/Utils/AI/Toolbox/OnCallTools.ts +12 -4
  33. package/Server/Utils/AnalyticsDatabase/Statement.ts +13 -1
  34. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +297 -6
  35. package/Server/Utils/Attribution.ts +4 -0
  36. package/Server/Utils/Marketing/MarketingEventUtil.ts +45 -7
  37. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +39 -1
  38. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +55 -3
  39. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +21 -0
  40. package/Server/Utils/StartServer.ts +12 -32
  41. package/Server/Utils/Telemetry/LlmCostBudgetEvaluator.ts +101 -4
  42. package/Server/Utils/Telemetry/LlmMetricSpend.ts +130 -0
  43. package/Server/Views/Partials/AnalyticsConsent.ejs +159 -102
  44. package/Server/Views/Partials/Head.ejs +2 -1
  45. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +776 -38
  46. package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +359 -0
  47. package/Tests/App/Dashboard/CorrelateGraph.test.tsx +865 -0
  48. package/Tests/App/Dashboard/CorrelationGraph.test.ts +346 -0
  49. package/Tests/App/Dashboard/CriteriaFilterConditionDropdown.test.tsx +256 -0
  50. package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +738 -0
  51. package/Tests/App/Dashboard/CriteriaFilterMonitorTypeChange.test.ts +1122 -0
  52. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +283 -0
  53. package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +407 -0
  54. package/Tests/App/Dashboard/MetricSeriesInvestigateMenu.test.tsx +5 -14
  55. package/Tests/App/Dashboard/MonitorCriteriaActionToggles.test.tsx +426 -0
  56. package/Tests/App/Dashboard/MonitorStepsCriteriaAlignmentWiring.test.tsx +352 -0
  57. package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +278 -0
  58. package/Tests/App/Dashboard/OnCallLayerShiftPreviewOverrides.test.ts +237 -0
  59. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +2 -2
  60. package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +460 -0
  61. package/Tests/App/Dashboard/SecurityEventAttributeUtil.test.ts +171 -0
  62. package/Tests/App/Dashboard/SecurityEventCorrelation.test.ts +857 -0
  63. package/Tests/App/Dashboard/SecurityEventDetailObservables.test.tsx +194 -0
  64. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +124 -0
  65. package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +79 -19
  66. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +382 -0
  67. package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +216 -0
  68. package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +590 -11
  69. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +757 -0
  70. package/Tests/Models/DiscoveryScanNameColumn.test.ts +293 -0
  71. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +564 -0
  72. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +120 -4
  73. package/Tests/Server/Middleware/GzipRequestBody.test.ts +725 -0
  74. package/Tests/Server/Middleware/MultipartFormData.test.ts +298 -0
  75. package/Tests/Server/Services/AddDetectionRuleDistinctCountColumnsMigration.test.ts +311 -0
  76. package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +205 -0
  77. package/Tests/Server/Services/DetectionRuleService.test.ts +134 -2
  78. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +7 -1
  79. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +131 -0
  80. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +933 -0
  81. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +194 -0
  82. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +800 -0
  83. package/Tests/Server/Services/OnCallScheduleAttachRosterRefresh.test.ts +244 -0
  84. package/Tests/Server/Services/SecurityEventService.test.ts +376 -0
  85. package/Tests/Server/Services/StatusPageResourceDuplicates.test.ts +703 -0
  86. package/Tests/Server/Services/TelemetryAttributeServiceSecurityEvent.test.ts +256 -0
  87. package/Tests/Server/Types/Workflow/Components/ComponentRegistryParity.test.ts +417 -0
  88. package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWhereOperators.test.ts +677 -0
  89. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +43 -0
  90. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +15 -11
  91. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +97 -1
  92. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +369 -8
  93. package/Tests/Server/Utils/SecurityEvent/SigmaClickhouseCompiler.test.ts +35 -0
  94. package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +368 -4
  95. package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +245 -0
  96. package/Tests/Server/Views/AnalyticsConsentPartial.test.ts +48 -5
  97. package/Tests/Types/Code/YamlSyntax.test.ts +396 -0
  98. package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +957 -0
  99. package/Tests/Types/Monitor/MonitorCriteriaActionValidation.test.ts +598 -0
  100. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +49 -0
  101. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +6 -6
  102. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +4 -4
  103. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +4 -3
  104. package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +193 -0
  105. package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +0 -12
  106. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +1 -17
  107. package/Tests/UI/Components/CodeEditor.test.tsx +474 -10
  108. package/Tests/UI/Components/Detail/YamlField.test.tsx +105 -0
  109. package/Tests/UI/Components/EntityDropdownLabelsBulkAdd.test.tsx +319 -0
  110. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +231 -0
  111. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +1 -0
  112. package/Tests/UI/Components/Forms/ValidationYAML.test.ts +234 -0
  113. package/Tests/UI/Components/ModelTable/AttributeColumns.test.tsx +573 -0
  114. package/Tests/UI/Components/ModelTable/BaseModelTableAttributeColumns.test.tsx +824 -0
  115. package/Tests/UI/Components/ModelTable/ColumnCustomizationModalAddableColumns.test.tsx +707 -0
  116. package/Tests/UI/Components/SideOver.test.tsx +1 -1
  117. package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +294 -0
  118. package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +436 -0
  119. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +6 -2
  120. package/Tests/UI/Components/Toggle.test.tsx +25 -0
  121. package/Tests/UI/Components/YamlEditor.test.tsx +847 -0
  122. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +252 -0
  123. package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +516 -0
  124. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +272 -0
  125. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +221 -0
  126. package/Tests/Utils/NetworkDiscovery/ScanNameUtil.test.ts +312 -0
  127. package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +164 -0
  128. package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +468 -0
  129. package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +472 -0
  130. package/Types/Code/YamlSyntax.ts +396 -0
  131. package/Types/Exception/ExceptionCode.ts +1 -0
  132. package/Types/Exception/PayloadTooLargeException.ts +8 -0
  133. package/Types/Marketing/Attribution.ts +10 -0
  134. package/Types/Marketing/MarketingEvent.ts +4 -0
  135. package/Types/Monitor/MonitorCriteriaInstance.ts +116 -56
  136. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +2 -1
  137. package/Types/NetworkAutomation/RuleRunResult.ts +84 -0
  138. package/Types/Permission.ts +47 -0
  139. package/Types/SecurityEvent/DetectionFindingConstants.ts +11 -0
  140. package/Types/Telemetry/LlmMetricConventions.ts +124 -0
  141. package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +3 -0
  142. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +10 -1
  143. package/UI/Components/CodeEditor/CodeEditor.tsx +241 -79
  144. package/UI/Components/CodeEditor/YamlEditor.tsx +369 -0
  145. package/UI/Components/Detail/Detail.tsx +10 -0
  146. package/UI/Components/EntityDropdown/EntityDropdown.tsx +33 -0
  147. package/UI/Components/Forms/Fields/FormField.tsx +31 -0
  148. package/UI/Components/Forms/Types/Field.ts +8 -0
  149. package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
  150. package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -0
  151. package/UI/Components/Forms/Validation.ts +46 -0
  152. package/UI/Components/Input/Input.tsx +3 -0
  153. package/UI/Components/ModelTable/AttributeColumns.tsx +321 -0
  154. package/UI/Components/ModelTable/BaseModelTable.tsx +263 -14
  155. package/UI/Components/ModelTable/Column.ts +8 -0
  156. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +310 -0
  157. package/UI/Components/ModelTable/ColumnPreference.ts +13 -1
  158. package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +2 -2
  159. package/UI/Components/SideOver/SideOver.tsx +5 -5
  160. package/UI/Components/StatusPage/ResourceGrid.tsx +82 -2
  161. package/UI/Components/StatusPage/ResourceList.tsx +197 -38
  162. package/UI/Components/Toggle/Toggle.tsx +9 -1
  163. package/UI/Components/Types/FieldType.ts +1 -0
  164. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +73 -1
  165. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +257 -0
  166. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +183 -0
  167. package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +95 -0
  168. package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +66 -0
  169. package/Utils/NetworkDiscovery/ScanNameUtil.ts +181 -0
  170. package/Utils/NetworkDiscovery/ScanTargetUtil.ts +82 -0
  171. package/Utils/StatusPage/ResourceExplorer.ts +258 -0
  172. package/Utils/Telemetry/LlmMetricQuery.ts +204 -0
  173. package/build/dist/Models/DatabaseModels/DetectionRule.js +57 -0
  174. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  175. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  176. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  177. package/build/dist/Models/DatabaseModels/NetworkDevice.js +45 -0
  178. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  179. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +609 -0
  180. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -0
  181. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +97 -0
  182. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  183. package/build/dist/Models/DatabaseModels/Project.js +76 -0
  184. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  185. package/build/dist/Models/DatabaseModels/User.js +76 -0
  186. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  187. package/build/dist/Server/API/TelemetryAPI.js +17 -0
  188. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  189. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.js +35 -0
  190. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.js.map +1 -0
  191. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.js +19 -0
  192. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.js.map +1 -0
  193. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.js +19 -0
  194. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.js.map +1 -0
  195. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js +21 -0
  196. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js.map +1 -0
  197. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js +42 -0
  198. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js.map +1 -0
  199. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js +22 -0
  200. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js.map +1 -0
  201. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
  202. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  203. package/build/dist/Server/Middleware/GzipRequestBody.js +224 -0
  204. package/build/dist/Server/Middleware/GzipRequestBody.js.map +1 -0
  205. package/build/dist/Server/Middleware/MultipartFormData.js +71 -2
  206. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  207. package/build/dist/Server/Services/DetectionRuleService.js +49 -4
  208. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  209. package/build/dist/Server/Services/Index.js +206 -0
  210. package/build/dist/Server/Services/Index.js.map +1 -1
  211. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +711 -0
  212. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -0
  213. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +155 -0
  214. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -0
  215. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +50 -0
  216. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  217. package/build/dist/Server/Services/NetworkDeviceService.js +124 -0
  218. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  219. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +68 -13
  220. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  221. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +1 -1
  222. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -1
  223. package/build/dist/Server/Services/ProjectService.js +25 -45
  224. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  225. package/build/dist/Server/Services/SecurityEventService.js +57 -5
  226. package/build/dist/Server/Services/SecurityEventService.js.map +1 -1
  227. package/build/dist/Server/Services/StatusPageResourceService.js +140 -0
  228. package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
  229. package/build/dist/Server/Services/TelemetryAttributeService.js +17 -0
  230. package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
  231. package/build/dist/Server/Services/UserService.js +2 -12
  232. package/build/dist/Server/Services/UserService.js.map +1 -1
  233. package/build/dist/Server/Types/Markdown.js +147 -61
  234. package/build/dist/Server/Types/Markdown.js.map +1 -1
  235. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +12 -4
  236. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -1
  237. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +12 -1
  238. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  239. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +246 -9
  240. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  241. package/build/dist/Server/Utils/Attribution.js.map +1 -1
  242. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +27 -7
  243. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
  244. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +26 -0
  245. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  246. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +42 -7
  247. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  248. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +18 -0
  249. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  250. package/build/dist/Server/Utils/StartServer.js +12 -21
  251. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  252. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js +76 -5
  253. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js.map +1 -1
  254. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +102 -0
  255. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -0
  256. package/build/dist/Types/Code/YamlSyntax.js +212 -0
  257. package/build/dist/Types/Code/YamlSyntax.js.map +1 -0
  258. package/build/dist/Types/Exception/ExceptionCode.js +1 -0
  259. package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
  260. package/build/dist/Types/Exception/PayloadTooLargeException.js +8 -0
  261. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -0
  262. package/build/dist/Types/Marketing/Attribution.js +10 -0
  263. package/build/dist/Types/Marketing/Attribution.js.map +1 -1
  264. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +112 -51
  265. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  266. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +2 -1
  267. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
  268. package/build/dist/Types/NetworkAutomation/RuleRunResult.js +24 -0
  269. package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
  270. package/build/dist/Types/Permission.js +41 -0
  271. package/build/dist/Types/Permission.js.map +1 -1
  272. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +9 -0
  273. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  274. package/build/dist/Types/Telemetry/LlmMetricConventions.js +98 -0
  275. package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -0
  276. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
  277. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
  278. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +5 -2
  279. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  280. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +206 -76
  281. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  282. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +201 -0
  283. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -0
  284. package/build/dist/UI/Components/Detail/Detail.js +9 -0
  285. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  286. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +16 -1
  287. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  288. package/build/dist/UI/Components/Forms/Fields/FormField.js +14 -1
  289. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  290. package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
  291. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
  292. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
  293. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -0
  294. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
  295. package/build/dist/UI/Components/Forms/Validation.js +27 -0
  296. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  297. package/build/dist/UI/Components/Input/Input.js +1 -1
  298. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  299. package/build/dist/UI/Components/ModelTable/AttributeColumns.js +159 -0
  300. package/build/dist/UI/Components/ModelTable/AttributeColumns.js.map +1 -0
  301. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +179 -17
  302. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  303. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +133 -2
  304. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
  305. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +7 -1
  306. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -1
  307. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +2 -2
  308. package/build/dist/UI/Components/SideOver/SideOver.js +5 -5
  309. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +28 -2
  310. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
  311. package/build/dist/UI/Components/StatusPage/ResourceList.js +87 -20
  312. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
  313. package/build/dist/UI/Components/Toggle/Toggle.js +9 -1
  314. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  315. package/build/dist/UI/Components/Types/FieldType.js +1 -0
  316. package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
  317. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +37 -1
  318. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  319. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +149 -0
  320. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -0
  321. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +121 -0
  322. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -0
  323. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +75 -0
  324. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -0
  325. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +59 -0
  326. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -0
  327. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js +120 -0
  328. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js.map +1 -0
  329. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +60 -0
  330. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -1
  331. package/build/dist/Utils/StatusPage/ResourceExplorer.js +171 -0
  332. package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -1
  333. package/build/dist/Utils/Telemetry/LlmMetricQuery.js +119 -0
  334. package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -0
  335. package/jest.config.json +2 -0
  336. package/package.json +1 -1
  337. package/tsconfig.json +2 -1
  338. package/Tests/UI/Components/Toast.test.tsx +0 -197
  339. package/Tests/UI/Components/ToastStacking.test.tsx +0 -198
  340. package/UI/Components/Toast/Toast.tsx +0 -189
  341. package/UI/Components/Toast/ToastInit.tsx +0 -110
  342. package/build/dist/UI/Components/Toast/Toast.js +0 -123
  343. package/build/dist/UI/Components/Toast/Toast.js.map +0 -1
  344. package/build/dist/UI/Components/Toast/ToastInit.js +0 -53
  345. package/build/dist/UI/Components/Toast/ToastInit.js.map +0 -1
@@ -10,6 +10,7 @@ import StatusPageResourceExplorerUtil, {
10
10
  StatusPageResourceNavigatorResult,
11
11
  StatusPageResourceNavigatorRow,
12
12
  StatusPageResourceSelection,
13
+ StatusPageResourceSelectionState,
13
14
  StatusPageResourceSelectionType,
14
15
  } from "../../../Utils/StatusPage/ResourceExplorer";
15
16
  import { describe, expect, test } from "@jest/globals";
@@ -928,4 +929,471 @@ describe("StatusPageResourceExplorerUtil", () => {
928
929
  ).toBe("12 sub groups");
929
930
  });
930
931
  });
932
+
933
+ /*
934
+ * Ticking rows, so that clearing a group is one decision rather than twenty
935
+ * seven (issue #3419).
936
+ *
937
+ * A selection is a set of id strings held by the pane, and the pane re-fetches
938
+ * the group after every write - so the two properties worth pinning down are
939
+ * that an operation only ever touches the resources it was handed, and that a
940
+ * no-op hands back the very set it was given rather than an equal copy. The
941
+ * second one is not tidiness: the set is React state, and returning a new
942
+ * instance for a no-op is a re-render of the whole pane per keystroke.
943
+ */
944
+ describe("selecting resources", () => {
945
+ type MakeSelectionFunction = (ids: Array<string>) => Set<string>;
946
+
947
+ const makeSelection: MakeSelectionFunction = (
948
+ ids: Array<string>,
949
+ ): Set<string> => {
950
+ return new Set<string>(ids);
951
+ };
952
+
953
+ /* A resource the server would never return: no id at all. */
954
+ type MakeIdlessResourceFunction = (name: string) => StatusPageResource;
955
+
956
+ const makeIdlessResource: MakeIdlessResourceFunction = (
957
+ name: string,
958
+ ): StatusPageResource => {
959
+ const resource: StatusPageResource = new StatusPageResource();
960
+ resource.displayName = name;
961
+
962
+ return resource;
963
+ };
964
+
965
+ describe("reading a resource's id", () => {
966
+ test("hands back the id as a string", () => {
967
+ expect(
968
+ StatusPageResourceExplorerUtil.getResourceId(
969
+ makeResource({ id: "a" }),
970
+ ),
971
+ ).toBe("a");
972
+ });
973
+
974
+ test("is null for a resource with no id", () => {
975
+ expect(
976
+ StatusPageResourceExplorerUtil.getResourceId(
977
+ makeIdlessResource("Nameless"),
978
+ ),
979
+ ).toBeNull();
980
+ });
981
+
982
+ test("is null rather than the empty string, which would collide", () => {
983
+ const resource: StatusPageResource = new StatusPageResource();
984
+ resource._id = "";
985
+
986
+ expect(
987
+ StatusPageResourceExplorerUtil.getResourceId(resource),
988
+ ).toBeNull();
989
+ });
990
+ });
991
+
992
+ describe("the ids a list offers", () => {
993
+ test("are in the order the list draws them", () => {
994
+ expect(
995
+ StatusPageResourceExplorerUtil.getResourceIds([
996
+ makeResource({ id: "c" }),
997
+ makeResource({ id: "a" }),
998
+ makeResource({ id: "b" }),
999
+ ]),
1000
+ ).toEqual(["c", "a", "b"]);
1001
+ });
1002
+
1003
+ test("skip anything that cannot be held on to", () => {
1004
+ expect(
1005
+ StatusPageResourceExplorerUtil.getResourceIds([
1006
+ makeResource({ id: "a" }),
1007
+ makeIdlessResource("Nameless"),
1008
+ makeResource({ id: "b" }),
1009
+ ]),
1010
+ ).toEqual(["a", "b"]);
1011
+ });
1012
+
1013
+ test("say each id once, however many rows carry it", () => {
1014
+ expect(
1015
+ StatusPageResourceExplorerUtil.getResourceIds([
1016
+ makeResource({ id: "a" }),
1017
+ makeResource({ id: "a" }),
1018
+ makeResource({ id: "b" }),
1019
+ ]),
1020
+ ).toEqual(["a", "b"]);
1021
+ });
1022
+
1023
+ test("are empty for an empty list", () => {
1024
+ expect(StatusPageResourceExplorerUtil.getResourceIds([])).toEqual([]);
1025
+ });
1026
+ });
1027
+
1028
+ describe("ticking one row", () => {
1029
+ test("adds an id that was not selected", () => {
1030
+ const next: Set<string> =
1031
+ StatusPageResourceExplorerUtil.toggleSelectedResourceId({
1032
+ selectedResourceIds: makeSelection(["a"]),
1033
+ resourceId: "b",
1034
+ });
1035
+
1036
+ expect([...next].sort()).toEqual(["a", "b"]);
1037
+ });
1038
+
1039
+ test("removes an id that was", () => {
1040
+ const next: Set<string> =
1041
+ StatusPageResourceExplorerUtil.toggleSelectedResourceId({
1042
+ selectedResourceIds: makeSelection(["a", "b"]),
1043
+ resourceId: "a",
1044
+ });
1045
+
1046
+ expect([...next]).toEqual(["b"]);
1047
+ });
1048
+
1049
+ test("leaves the set it was given alone", () => {
1050
+ const current: Set<string> = makeSelection(["a"]);
1051
+
1052
+ const next: Set<string> =
1053
+ StatusPageResourceExplorerUtil.toggleSelectedResourceId({
1054
+ selectedResourceIds: current,
1055
+ resourceId: "b",
1056
+ });
1057
+
1058
+ expect(next).not.toBe(current);
1059
+ expect([...current]).toEqual(["a"]);
1060
+ });
1061
+ });
1062
+
1063
+ describe("the box at the top of the list", () => {
1064
+ test("selects every resource it was handed", () => {
1065
+ const next: Set<string> =
1066
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1067
+ selectedResourceIds: makeSelection([]),
1068
+ statusPageResources: [
1069
+ makeResource({ id: "a" }),
1070
+ makeResource({ id: "b" }),
1071
+ ],
1072
+ isSelected: true,
1073
+ });
1074
+
1075
+ expect([...next].sort()).toEqual(["a", "b"]);
1076
+ });
1077
+
1078
+ /*
1079
+ * The list is filtered as often as not, and the rows the search hid are
1080
+ * still selected. Un-ticking over four matches must not drop the twenty
1081
+ * that were selected before the operator started typing.
1082
+ */
1083
+ test("leaves selected rows it was not handed alone, in both directions", () => {
1084
+ const selected: Set<string> =
1085
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1086
+ selectedResourceIds: makeSelection(["hidden"]),
1087
+ statusPageResources: [makeResource({ id: "shown" })],
1088
+ isSelected: true,
1089
+ });
1090
+
1091
+ expect([...selected].sort()).toEqual(["hidden", "shown"]);
1092
+
1093
+ const deselected: Set<string> =
1094
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1095
+ selectedResourceIds: selected,
1096
+ statusPageResources: [makeResource({ id: "shown" })],
1097
+ isSelected: false,
1098
+ });
1099
+
1100
+ expect([...deselected]).toEqual(["hidden"]);
1101
+ });
1102
+
1103
+ test("ignores rows that cannot be selected at all", () => {
1104
+ const next: Set<string> =
1105
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1106
+ selectedResourceIds: makeSelection([]),
1107
+ statusPageResources: [
1108
+ makeResource({ id: "a" }),
1109
+ makeIdlessResource("Nameless"),
1110
+ ],
1111
+ isSelected: true,
1112
+ });
1113
+
1114
+ expect([...next]).toEqual(["a"]);
1115
+ });
1116
+
1117
+ test("hands back the same set when everything was already selected", () => {
1118
+ const current: Set<string> = makeSelection(["a", "b"]);
1119
+
1120
+ expect(
1121
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1122
+ selectedResourceIds: current,
1123
+ statusPageResources: [
1124
+ makeResource({ id: "a" }),
1125
+ makeResource({ id: "b" }),
1126
+ ],
1127
+ isSelected: true,
1128
+ }),
1129
+ ).toBe(current);
1130
+ });
1131
+
1132
+ test("hands back the same set when nothing handed in was selected", () => {
1133
+ const current: Set<string> = makeSelection(["other"]);
1134
+
1135
+ expect(
1136
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1137
+ selectedResourceIds: current,
1138
+ statusPageResources: [makeResource({ id: "a" })],
1139
+ isSelected: false,
1140
+ }),
1141
+ ).toBe(current);
1142
+ });
1143
+
1144
+ test("hands back the same set for an empty list", () => {
1145
+ const current: Set<string> = makeSelection(["a"]);
1146
+
1147
+ expect(
1148
+ StatusPageResourceExplorerUtil.setResourcesSelected({
1149
+ selectedResourceIds: current,
1150
+ statusPageResources: [],
1151
+ isSelected: true,
1152
+ }),
1153
+ ).toBe(current);
1154
+ });
1155
+ });
1156
+
1157
+ describe("what the box at the top of the list looks like", () => {
1158
+ type StateFunction = (
1159
+ resources: Array<StatusPageResource>,
1160
+ ids: Array<string>,
1161
+ ) => StatusPageResourceSelectionState;
1162
+
1163
+ const state: StateFunction = (
1164
+ resources: Array<StatusPageResource>,
1165
+ ids: Array<string>,
1166
+ ): StatusPageResourceSelectionState => {
1167
+ return StatusPageResourceExplorerUtil.getSelectionState({
1168
+ statusPageResources: resources,
1169
+ selectedResourceIds: makeSelection(ids),
1170
+ });
1171
+ };
1172
+
1173
+ test("is empty when nothing is selected", () => {
1174
+ expect(
1175
+ state([makeResource({ id: "a" }), makeResource({ id: "b" })], []),
1176
+ ).toEqual({
1177
+ isAllSelected: false,
1178
+ isIndeterminate: false,
1179
+ selectedCount: 0,
1180
+ selectableCount: 2,
1181
+ });
1182
+ });
1183
+
1184
+ test("is half filled when some of them are", () => {
1185
+ expect(
1186
+ state([makeResource({ id: "a" }), makeResource({ id: "b" })], ["a"]),
1187
+ ).toEqual({
1188
+ isAllSelected: false,
1189
+ isIndeterminate: true,
1190
+ selectedCount: 1,
1191
+ selectableCount: 2,
1192
+ });
1193
+ });
1194
+
1195
+ test("is filled when all of them are", () => {
1196
+ expect(
1197
+ state(
1198
+ [makeResource({ id: "a" }), makeResource({ id: "b" })],
1199
+ ["a", "b"],
1200
+ ),
1201
+ ).toEqual({
1202
+ isAllSelected: true,
1203
+ isIndeterminate: false,
1204
+ selectedCount: 2,
1205
+ selectableCount: 2,
1206
+ });
1207
+ });
1208
+
1209
+ /*
1210
+ * A ticked box over nothing to tick reads as a selection that was lost -
1211
+ * which is exactly what an operator sees when a search matches nothing.
1212
+ */
1213
+ test("is never filled over an empty list", () => {
1214
+ expect(state([], ["a"])).toEqual({
1215
+ isAllSelected: false,
1216
+ isIndeterminate: false,
1217
+ selectedCount: 0,
1218
+ selectableCount: 0,
1219
+ });
1220
+ });
1221
+
1222
+ /*
1223
+ * The selection outlives the filter, so it routinely holds ids that the
1224
+ * rows on screen know nothing about. They must not make the box on screen
1225
+ * look fuller than it is.
1226
+ */
1227
+ test("counts only the rows it was handed", () => {
1228
+ expect(state([makeResource({ id: "a" })], ["a", "elsewhere"])).toEqual({
1229
+ isAllSelected: true,
1230
+ isIndeterminate: false,
1231
+ selectedCount: 1,
1232
+ selectableCount: 1,
1233
+ });
1234
+ });
1235
+
1236
+ test("is filled when every selectable row is selected, id-less ones aside", () => {
1237
+ expect(
1238
+ state(
1239
+ [makeResource({ id: "a" }), makeIdlessResource("Nameless")],
1240
+ ["a"],
1241
+ ),
1242
+ ).toEqual({
1243
+ isAllSelected: true,
1244
+ isIndeterminate: false,
1245
+ selectedCount: 1,
1246
+ selectableCount: 1,
1247
+ });
1248
+ });
1249
+ });
1250
+
1251
+ describe("resolving a selection to resources", () => {
1252
+ test("hands them back in the order the list holds them", () => {
1253
+ const resources: Array<StatusPageResource> = [
1254
+ makeResource({ id: "a", monitorName: "API" }),
1255
+ makeResource({ id: "b", monitorName: "Database" }),
1256
+ makeResource({ id: "c", monitorName: "Cache" }),
1257
+ ];
1258
+
1259
+ const selected: Array<StatusPageResource> =
1260
+ StatusPageResourceExplorerUtil.getSelectedResources({
1261
+ statusPageResources: resources,
1262
+ /* Ticked bottom up; reported top down. */
1263
+ selectedResourceIds: makeSelection(["c", "a"]),
1264
+ });
1265
+
1266
+ expect(
1267
+ selected.map((resource: StatusPageResource) => {
1268
+ return StatusPageResourceExplorerUtil.getResourceName(resource);
1269
+ }),
1270
+ ).toEqual(["API", "Cache"]);
1271
+ });
1272
+
1273
+ test("drops ids that match nothing on screen", () => {
1274
+ expect(
1275
+ StatusPageResourceExplorerUtil.getSelectedResources({
1276
+ statusPageResources: [makeResource({ id: "a" })],
1277
+ selectedResourceIds: makeSelection(["a", "gone"]),
1278
+ }).length,
1279
+ ).toBe(1);
1280
+ });
1281
+
1282
+ test("hands back one resource per id", () => {
1283
+ expect(
1284
+ StatusPageResourceExplorerUtil.getSelectedResources({
1285
+ statusPageResources: [
1286
+ makeResource({ id: "a" }),
1287
+ makeResource({ id: "a" }),
1288
+ ],
1289
+ selectedResourceIds: makeSelection(["a"]),
1290
+ }).length,
1291
+ ).toBe(1);
1292
+ });
1293
+
1294
+ test("is empty when nothing is selected", () => {
1295
+ expect(
1296
+ StatusPageResourceExplorerUtil.getSelectedResources({
1297
+ statusPageResources: [makeResource({ id: "a" })],
1298
+ selectedResourceIds: makeSelection([]),
1299
+ }),
1300
+ ).toEqual([]);
1301
+ });
1302
+ });
1303
+
1304
+ describe("keeping a selection honest across a refetch", () => {
1305
+ test("drops whatever the group no longer holds", () => {
1306
+ const next: Set<string> =
1307
+ StatusPageResourceExplorerUtil.retainSelectedResourceIds({
1308
+ selectedResourceIds: makeSelection(["a", "b", "c"]),
1309
+ statusPageResources: [
1310
+ makeResource({ id: "a" }),
1311
+ makeResource({ id: "c" }),
1312
+ ],
1313
+ });
1314
+
1315
+ expect([...next].sort()).toEqual(["a", "c"]);
1316
+ });
1317
+
1318
+ test("hands back the same set when nothing was dropped", () => {
1319
+ const current: Set<string> = makeSelection(["a", "b"]);
1320
+
1321
+ expect(
1322
+ StatusPageResourceExplorerUtil.retainSelectedResourceIds({
1323
+ selectedResourceIds: current,
1324
+ statusPageResources: [
1325
+ makeResource({ id: "a" }),
1326
+ makeResource({ id: "b" }),
1327
+ ],
1328
+ }),
1329
+ ).toBe(current);
1330
+ });
1331
+
1332
+ test("hands back the same empty set rather than a new one", () => {
1333
+ const current: Set<string> = makeSelection([]);
1334
+
1335
+ expect(
1336
+ StatusPageResourceExplorerUtil.retainSelectedResourceIds({
1337
+ selectedResourceIds: current,
1338
+ statusPageResources: [makeResource({ id: "a" })],
1339
+ }),
1340
+ ).toBe(current);
1341
+ });
1342
+
1343
+ test("empties a selection whose group came back empty", () => {
1344
+ expect(
1345
+ StatusPageResourceExplorerUtil.retainSelectedResourceIds({
1346
+ selectedResourceIds: makeSelection(["a"]),
1347
+ statusPageResources: [],
1348
+ }).size,
1349
+ ).toBe(0);
1350
+ });
1351
+ });
1352
+
1353
+ describe("what the confirmation says", () => {
1354
+ test("uses the singular for one resource, and says the monitor survives", () => {
1355
+ expect(
1356
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmTitle({
1357
+ count: 1,
1358
+ }),
1359
+ ).toBe("Remove 1 resource");
1360
+
1361
+ expect(
1362
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmMessage({
1363
+ count: 1,
1364
+ }),
1365
+ ).toBe(
1366
+ "Are you sure you want to remove 1 resource from this status page? The monitor itself is not deleted.",
1367
+ );
1368
+ });
1369
+
1370
+ test("uses the plural for several, and says the monitors survive", () => {
1371
+ expect(
1372
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmTitle({
1373
+ count: 27,
1374
+ }),
1375
+ ).toBe("Remove 27 resources");
1376
+
1377
+ expect(
1378
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmMessage({
1379
+ count: 27,
1380
+ }),
1381
+ ).toContain("remove 27 resources from this status page");
1382
+
1383
+ expect(
1384
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmMessage({
1385
+ count: 27,
1386
+ }),
1387
+ ).toContain("The monitors themselves are not deleted.");
1388
+ });
1389
+
1390
+ test("groups the thousands, because the number is the whole warning", () => {
1391
+ expect(
1392
+ StatusPageResourceExplorerUtil.getBulkRemoveConfirmTitle({
1393
+ count: 1506,
1394
+ }),
1395
+ ).toBe(`Remove ${(1506).toLocaleString()} resources`);
1396
+ });
1397
+ });
1398
+ });
931
1399
  });