@oneuptime/common 13.0.8 → 14.0.1

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 (514) hide show
  1. package/Models/AnalyticsModels/AuditLog.ts +23 -15
  2. package/Models/DatabaseModels/GlobalConfig.ts +24 -0
  3. package/Models/DatabaseModels/Index.ts +4 -0
  4. package/Models/DatabaseModels/Monitor.ts +3 -2
  5. package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
  6. package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +2 -0
  7. package/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.ts +522 -0
  8. package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +38 -4
  9. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.ts +603 -0
  10. package/Scripts/generate-service-worker.js +65 -4
  11. package/Server/API/BaseAPI.ts +26 -5
  12. package/Server/API/GlobalConfigAPI.ts +228 -462
  13. package/Server/API/ProjectOIDC.ts +25 -16
  14. package/Server/API/ProjectSSO.ts +24 -16
  15. package/Server/API/StatusPageAPI.ts +100 -42
  16. package/Server/API/TeamMemberAPI.ts +10 -1
  17. package/Server/Enterprise/EnterpriseEdition.ts +649 -0
  18. package/Server/Enterprise/EnterpriseFeature.ts +48 -0
  19. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
  20. package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
  21. package/Server/EnvironmentConfig.ts +147 -2
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.ts +248 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.ts +19 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  26. package/Server/Middleware/UserAuthorization.ts +38 -16
  27. package/Server/Services/AuditLogService.ts +84 -1079
  28. package/Server/Services/DatabaseService.ts +10 -0
  29. package/Server/Services/EnterpriseLicenseService.ts +38 -0
  30. package/Server/Services/GlobalConfigService.ts +80 -1
  31. package/Server/Services/Index.ts +4 -0
  32. package/Server/Services/MonitorProbeService.ts +116 -20
  33. package/Server/Services/MonitorService.ts +59 -6
  34. package/Server/Services/MonitorStatusTimelineService.ts +284 -0
  35. package/Server/Services/MonitorTemplateService.ts +26 -0
  36. package/Server/Services/ProjectService.ts +284 -0
  37. package/Server/Services/RumSessionPinService.ts +25 -6
  38. package/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.ts +385 -0
  39. package/Server/Services/ServiceLevelObjectiveLabelRuleService.ts +51 -0
  40. package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +92 -16
  41. package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +36 -1
  42. package/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.ts +521 -0
  43. package/Server/Services/ServiceLevelObjectiveOwnerRuleService.ts +51 -0
  44. package/Server/Services/ServiceLevelObjectiveService.ts +28 -0
  45. package/Server/Services/StatusPagePrivateUserService.ts +7 -3
  46. package/Server/Services/StatusPageService.ts +78 -1
  47. package/Server/Services/TeamMemberService.ts +11 -0
  48. package/Server/Services/TeamService.ts +10 -0
  49. package/Server/Services/UserService.ts +10 -17
  50. package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
  51. package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
  52. package/Server/Types/Database/Permissions/TablePermission.ts +10 -3
  53. package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
  54. package/Server/Types/Markdown.ts +41 -0
  55. package/Server/Types/Workflow/Components/Telegram/SendMessageToChat.ts +27 -1
  56. package/Server/Utils/AI/Toolbox/SloTools.ts +1 -0
  57. package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
  58. package/Server/Utils/EditionEnforcement.ts +233 -0
  59. package/Server/Utils/FrontendEnvironment.ts +41 -2
  60. package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
  61. package/Server/Utils/Monitor/AffectedResourceList.ts +148 -0
  62. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +1 -1
  63. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
  64. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +1 -1
  65. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +720 -465
  66. package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
  67. package/Server/Utils/Monitor/RootCauseList.ts +139 -0
  68. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +28 -0
  69. package/Server/Utils/Slo/SloRulePatternValidator.ts +42 -0
  70. package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
  71. package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
  72. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
  73. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
  74. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
  75. package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
  76. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
  77. package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
  78. package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
  79. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
  80. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
  81. package/Tests/App/Dashboard/FeedFilterSortIntegration.test.tsx +1632 -0
  82. package/Tests/App/Dashboard/FeedOptionsLocales.test.ts +250 -0
  83. package/Tests/App/Dashboard/FeedOrdering.test.ts +279 -9
  84. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
  85. package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +60 -1
  86. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +594 -3
  87. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
  88. package/Tests/App/Dashboard/ProductOrientation.test.tsx +646 -0
  89. package/Tests/App/Dashboard/ResourceFeed.test.tsx +612 -2
  90. package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +30 -0
  91. package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +1202 -0
  92. package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +52 -1
  93. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +45 -9
  94. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
  95. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
  96. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -83
  97. package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
  98. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
  99. package/Tests/App/Dashboard/SloFeed.test.tsx +106 -1
  100. package/Tests/App/Dashboard/SloMonitorRuleCriteria.test.tsx +566 -0
  101. package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +6 -4
  102. package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +186 -0
  103. package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +388 -44
  104. package/Tests/App/Dashboard/SloOverviewLayout.test.tsx +613 -0
  105. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
  106. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
  107. package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
  108. package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
  109. package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +0 -8
  110. package/Tests/Models/DatabaseModels/SloLabelAndOwnerRuleModels.test.ts +404 -0
  111. package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +17 -1
  112. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  113. package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
  114. package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
  115. package/Tests/Server/API/GlobalConfigLicense.test.ts +742 -497
  116. package/Tests/Server/API/OnCallReadinessAPI.test.ts +35 -909
  117. package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
  118. package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
  119. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
  120. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
  121. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
  122. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
  123. package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
  124. package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
  125. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
  126. package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
  127. package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
  128. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
  129. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
  130. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  131. package/Tests/Server/Infrastructure/Postgres/AddSloLabelAndOwnerRulesMigration.test.ts +407 -0
  132. package/Tests/Server/Infrastructure/Postgres/AddSloMonitorRuleMonitorTypeMigration.test.ts +171 -0
  133. package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +88 -4
  134. package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
  135. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
  136. package/Tests/Server/Services/AuditLogService.test.ts +460 -990
  137. package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
  138. package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +104 -0
  139. package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
  140. package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
  141. package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
  142. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
  143. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
  144. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
  145. package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
  146. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +48 -1
  147. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -0
  148. package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
  149. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +1170 -0
  150. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleServices.test.ts +172 -0
  151. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +323 -0
  152. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +115 -0
  153. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleTriggers.test.ts +21 -2
  154. package/Tests/Server/Services/ServiceLevelObjectiveMonitorTypePostgres.test.ts +480 -0
  155. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +162 -0
  156. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
  157. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
  158. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +45 -6
  159. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
  160. package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
  161. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
  162. package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +745 -0
  163. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
  164. package/Tests/Server/Types/Markdown.test.ts +183 -1
  165. package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +49 -0
  166. package/Tests/Server/Types/Workflow/Components/TelegramSendMessageToChat.test.ts +331 -0
  167. package/Tests/Server/Utils/AI/SloTools.test.ts +10 -0
  168. package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
  169. package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
  170. package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
  171. package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
  172. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
  173. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
  174. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +1 -1
  175. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +1339 -96
  176. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +1101 -0
  177. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +106 -80
  178. package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
  179. package/Tests/Server/Utils/Monitor/RootCauseList.test.ts +252 -0
  180. package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +154 -0
  181. package/Tests/Server/Utils/SSRFProtection.test.ts +111 -0
  182. package/Tests/Server/Utils/Slo/SloRulePatternValidator.test.ts +67 -0
  183. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +213 -0
  184. package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
  185. package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
  186. package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
  187. package/Tests/Types/API/Route.test.ts +56 -0
  188. package/Tests/Types/API/URLSchemeLikePath.test.ts +304 -0
  189. package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
  190. package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
  191. package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
  192. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +84 -178
  193. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
  194. package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
  195. package/Tests/UI/Components/FeedOptions.test.ts +1404 -0
  196. package/Tests/UI/Components/FeedOptionsButton.test.tsx +2603 -0
  197. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
  198. package/Tests/UI/Components/Icon.test.tsx +26 -0
  199. package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
  200. package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
  201. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  202. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
  203. package/Tests/UI/Components/useFeedItemsViewKey.test.tsx +1017 -0
  204. package/Tests/UI/Components/useFeedOptions.test.tsx +1107 -0
  205. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
  206. package/Tests/Utils/HostAddressUtil.test.ts +138 -0
  207. package/Tests/Utils/LabelRuleImportExport.test.ts +102 -0
  208. package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
  209. package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
  210. package/Tests/Utils/Slo/SloDuration.test.ts +115 -24
  211. package/Tests/Utils/Slo/SloHealth.test.ts +93 -10
  212. package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +109 -0
  213. package/Tests/Utils/Slo/SloOverviewText.test.ts +64 -0
  214. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
  215. package/Types/API/Hostname.ts +63 -16
  216. package/Types/API/Route.ts +19 -2
  217. package/Types/API/URL.ts +26 -2
  218. package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
  219. package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
  220. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
  221. package/Types/Database/CanonicalModelInstance.ts +102 -0
  222. package/Types/Database/TableColumn.ts +20 -6
  223. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
  224. package/Types/IP/IPv6.ts +6 -1
  225. package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +6 -5
  226. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +9 -0
  227. package/Types/Monitor/MonitorStep.ts +6 -1
  228. package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
  229. package/Types/Permission.ts +90 -0
  230. package/Types/Rules/RuleCriteriaFieldRegistry.ts +11 -0
  231. package/Types/Rules/RuleRun.ts +4 -0
  232. package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
  233. package/UI/Components/EditionLabel/EditionLabel.tsx +796 -1195
  234. package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
  235. package/UI/Components/Feed/FeedOptions.ts +427 -0
  236. package/UI/Components/Feed/FeedOptionsButton.tsx +692 -0
  237. package/UI/Components/Feed/useFeedItems.ts +28 -9
  238. package/UI/Components/Feed/useFeedOptions.ts +225 -0
  239. package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
  240. package/UI/Components/Icon/Icon.tsx +1 -1
  241. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  242. package/UI/Components/ModelList/ModelList.tsx +11 -1
  243. package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
  244. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
  245. package/UI/esbuild-enterprise.js +263 -0
  246. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
  247. package/Utils/HostAddressUtil.ts +94 -0
  248. package/Utils/LabelRuleImportExport.ts +27 -9
  249. package/Utils/Monitor/MetricValueFormatter.ts +2 -2
  250. package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
  251. package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
  252. package/Utils/Rules/MonitorTypeRuleCriteria.ts +31 -0
  253. package/Utils/Slo/SloDuration.ts +22 -6
  254. package/Utils/Slo/SloHealth.ts +8 -7
  255. package/Utils/Slo/SloMonitorRuleCriteria.ts +33 -1
  256. package/Utils/Slo/SloOverviewText.ts +33 -0
  257. package/Utils/Slo/SloProjection.ts +4 -3
  258. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
  259. package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
  260. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  261. package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
  262. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  263. package/build/dist/Models/DatabaseModels/Index.js +4 -0
  264. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  265. package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
  266. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  267. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
  268. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  269. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +2 -0
  270. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -1
  271. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js +530 -0
  272. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js.map +1 -0
  273. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +39 -4
  274. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -1
  275. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js +612 -0
  276. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js.map +1 -0
  277. package/build/dist/Server/API/BaseAPI.js +26 -5
  278. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  279. package/build/dist/Server/API/GlobalConfigAPI.js +148 -344
  280. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  281. package/build/dist/Server/API/ProjectOIDC.js +24 -16
  282. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  283. package/build/dist/Server/API/ProjectSSO.js +24 -16
  284. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  285. package/build/dist/Server/API/StatusPageAPI.js +93 -43
  286. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  287. package/build/dist/Server/API/TeamMemberAPI.js +8 -1
  288. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  289. package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
  290. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
  291. package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
  292. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
  293. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
  294. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
  295. package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
  296. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
  297. package/build/dist/Server/EnvironmentConfig.js +84 -2
  298. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  299. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
  300. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
  301. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js +93 -0
  302. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js.map +1 -0
  303. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js +12 -0
  304. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js.map +1 -0
  305. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  306. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  307. package/build/dist/Server/Middleware/UserAuthorization.js +30 -11
  308. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  309. package/build/dist/Server/Services/AuditLogService.js +71 -740
  310. package/build/dist/Server/Services/AuditLogService.js.map +1 -1
  311. package/build/dist/Server/Services/DatabaseService.js +7 -0
  312. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  313. package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
  314. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  315. package/build/dist/Server/Services/GlobalConfigService.js +63 -0
  316. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  317. package/build/dist/Server/Services/Index.js +4 -0
  318. package/build/dist/Server/Services/Index.js.map +1 -1
  319. package/build/dist/Server/Services/MonitorProbeService.js +90 -17
  320. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  321. package/build/dist/Server/Services/MonitorService.js +48 -6
  322. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  323. package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
  324. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  325. package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
  326. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  327. package/build/dist/Server/Services/ProjectService.js +214 -0
  328. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  329. package/build/dist/Server/Services/RumSessionPinService.js +24 -6
  330. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  331. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js +295 -0
  332. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js.map +1 -0
  333. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js +56 -0
  334. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js.map +1 -0
  335. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +59 -14
  336. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
  337. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +22 -1
  338. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -1
  339. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js +400 -0
  340. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js.map +1 -0
  341. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js +56 -0
  342. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js.map +1 -0
  343. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +21 -0
  344. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
  345. package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
  346. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  347. package/build/dist/Server/Services/StatusPageService.js +71 -0
  348. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  349. package/build/dist/Server/Services/TeamMemberService.js +10 -0
  350. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  351. package/build/dist/Server/Services/TeamService.js +9 -0
  352. package/build/dist/Server/Services/TeamService.js.map +1 -1
  353. package/build/dist/Server/Services/UserService.js +10 -16
  354. package/build/dist/Server/Services/UserService.js.map +1 -1
  355. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
  356. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  357. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
  358. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  359. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +10 -3
  360. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  361. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
  362. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  363. package/build/dist/Server/Types/Markdown.js +31 -0
  364. package/build/dist/Server/Types/Markdown.js.map +1 -1
  365. package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js +20 -1
  366. package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js.map +1 -1
  367. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +1 -0
  368. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
  369. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
  370. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
  371. package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
  372. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
  373. package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
  374. package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
  375. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
  376. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
  377. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +67 -0
  378. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
  379. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +1 -1
  380. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  381. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  382. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +1 -1
  383. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +585 -367
  384. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  385. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
  386. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
  387. package/build/dist/Server/Utils/Monitor/RootCauseList.js +101 -0
  388. package/build/dist/Server/Utils/Monitor/RootCauseList.js.map +1 -0
  389. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +28 -0
  390. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  391. package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js +28 -0
  392. package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js.map +1 -0
  393. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
  394. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  395. package/build/dist/Types/API/Hostname.js +59 -11
  396. package/build/dist/Types/API/Hostname.js.map +1 -1
  397. package/build/dist/Types/API/Route.js +18 -2
  398. package/build/dist/Types/API/Route.js.map +1 -1
  399. package/build/dist/Types/API/URL.js +23 -2
  400. package/build/dist/Types/API/URL.js.map +1 -1
  401. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
  402. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
  403. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
  404. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
  405. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
  406. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
  407. package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
  408. package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
  409. package/build/dist/Types/Database/TableColumn.js +19 -6
  410. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  411. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
  412. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
  413. package/build/dist/Types/IP/IPv6.js +6 -1
  414. package/build/dist/Types/IP/IPv6.js.map +1 -1
  415. package/build/dist/Types/Monitor/MonitorStep.js +5 -0
  416. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  417. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
  418. package/build/dist/Types/Permission.js +84 -0
  419. package/build/dist/Types/Permission.js.map +1 -1
  420. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +11 -0
  421. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  422. package/build/dist/Types/Rules/RuleRun.js +4 -0
  423. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  424. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
  425. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
  426. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +414 -585
  427. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  428. package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
  429. package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
  430. package/build/dist/UI/Components/Feed/FeedOptions.js +235 -0
  431. package/build/dist/UI/Components/Feed/FeedOptions.js.map +1 -0
  432. package/build/dist/UI/Components/Feed/FeedOptionsButton.js +346 -0
  433. package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -0
  434. package/build/dist/UI/Components/Feed/useFeedItems.js +17 -7
  435. package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -1
  436. package/build/dist/UI/Components/Feed/useFeedOptions.js +130 -0
  437. package/build/dist/UI/Components/Feed/useFeedOptions.js.map +1 -0
  438. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
  439. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  440. package/build/dist/UI/Components/Icon/Icon.js +1 -1
  441. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  442. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  443. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  444. package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
  445. package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
  446. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
  447. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  448. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
  449. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  450. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
  451. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  452. package/build/dist/Utils/HostAddressUtil.js +80 -0
  453. package/build/dist/Utils/HostAddressUtil.js.map +1 -0
  454. package/build/dist/Utils/LabelRuleImportExport.js +22 -6
  455. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  456. package/build/dist/Utils/Monitor/MetricValueFormatter.js +2 -2
  457. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
  458. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
  459. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
  460. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
  461. package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js +18 -0
  462. package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js.map +1 -0
  463. package/build/dist/Utils/Slo/SloDuration.js +13 -5
  464. package/build/dist/Utils/Slo/SloDuration.js.map +1 -1
  465. package/build/dist/Utils/Slo/SloHealth.js +8 -7
  466. package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
  467. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +16 -1
  468. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -1
  469. package/build/dist/Utils/Slo/SloOverviewText.js +16 -0
  470. package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -1
  471. package/build/dist/Utils/Slo/SloProjection.js.map +1 -1
  472. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  473. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
  474. package/jest.config.json +3 -1
  475. package/package.json +1 -1
  476. package/test-setup.sh +103 -34
  477. package/tsconfig.json +13 -0
  478. package/Server/API/EnterpriseLicenseAPI.ts +0 -925
  479. package/Server/API/TeamComplianceAPI.ts +0 -158
  480. package/Server/Middleware/SCIMAuthorization.ts +0 -141
  481. package/Server/Services/TeamComplianceService.ts +0 -733
  482. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
  483. package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
  484. package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
  485. package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
  486. package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +0 -761
  487. package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
  488. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
  489. package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +0 -321
  490. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
  491. package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
  492. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
  493. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
  494. package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
  495. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
  496. package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
  497. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
  498. package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
  499. package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
  500. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
  501. package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
  502. package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
  503. package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
  504. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
  505. package/build/dist/Server/Services/TeamComplianceService.js +0 -537
  506. package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
  507. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
  508. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
  509. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
  510. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
  511. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
  512. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
  513. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
  514. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
@@ -7,7 +7,14 @@ import {
7
7
  test,
8
8
  } from "@jest/globals";
9
9
  import "@testing-library/jest-dom";
10
- import { cleanup, render, screen, waitFor } from "@testing-library/react";
10
+ import {
11
+ cleanup,
12
+ fireEvent,
13
+ render,
14
+ screen,
15
+ waitFor,
16
+ within,
17
+ } from "@testing-library/react";
11
18
  import * as React from "react";
12
19
 
13
20
  /*
@@ -49,8 +56,16 @@ import ServiceLevelObjectiveFeed, {
49
56
  ServiceLevelObjectiveFeedEventType,
50
57
  } from "../../../Models/DatabaseModels/ServiceLevelObjectiveFeed";
51
58
  import { Yellow } from "../../../Types/BrandColors";
59
+ import Includes from "../../../Types/BaseDatabase/Includes";
60
+ import SortOrder from "../../../Types/BaseDatabase/SortOrder";
52
61
  import IconProp from "../../../Types/Icon/IconProp";
53
62
  import ObjectID from "../../../Types/ObjectID";
63
+ import {
64
+ DEFAULT_FEED_OPTIONS,
65
+ FEED_OPTIONS_TEXT,
66
+ FeedOptions,
67
+ getFeedOptionsSummary,
68
+ } from "../../../UI/Components/Feed/FeedOptions";
54
69
 
55
70
  /*
56
71
  * The SLO feed is the generic ResourceFeed, wired once in
@@ -72,6 +87,8 @@ beforeEach(() => {
72
87
  mockGetListResponse = (): Promise<unknown> => {
73
88
  return Promise.resolve({ data: [], count: 0 });
74
89
  };
90
+ // A remembered sort order would change what the first request asks for.
91
+ window.localStorage.clear();
75
92
  });
76
93
 
77
94
  afterEach(() => {
@@ -94,6 +111,8 @@ describe("getSloResourceFeedProps", () => {
94
111
  );
95
112
  // Both the page and any embedded feed get the SLO icons from here.
96
113
  expect(props.getIcon).toBe(getSloFeedEventIcon);
114
+ // ...and the event types the Filter & Sort checklist offers.
115
+ expect(props.eventTypes).toEqual(ALL_EVENT_TYPES);
97
116
  });
98
117
 
99
118
  test("lets an embedded feed use its own title and description", () => {
@@ -254,6 +273,9 @@ describe("SloFeed", () => {
254
273
  expect(request.query.serviceLevelObjectiveId).toBe(SLO_ID);
255
274
  expect(request.select.serviceLevelObjectiveFeedEventType).toBe(true);
256
275
  expect(request.select.postedAt).toBe(true);
276
+ // Untouched, Filter & Sort adds nothing to the query and keeps the order.
277
+ expect(Object.keys(request.query)).toEqual(["serviceLevelObjectiveId"]);
278
+ expect(request.sort).toEqual({ postedAt: SortOrder.Descending });
257
279
  });
258
280
 
259
281
  test("renders what the SLO's history says, under the default title", async () => {
@@ -286,4 +308,87 @@ describe("SloFeed", () => {
286
308
 
287
309
  expect(screen.getByText("Recent activity")).toBeInTheDocument();
288
310
  });
311
+
312
+ test("offers Filter & Sort by its label, described by what the feed shows, and filters on the SLO's own event type column", async () => {
313
+ type GetExpectedSummary = (options: FeedOptions) => string;
314
+
315
+ /*
316
+ * Built by the same function the button uses, so the wording can change
317
+ * freely - what is pinned is that the description follows the feed's
318
+ * live order and filter, counted over the SLO's own event types.
319
+ */
320
+ const getExpectedSummary: GetExpectedSummary = (
321
+ options: FeedOptions,
322
+ ): string => {
323
+ return getFeedOptionsSummary({
324
+ options: options,
325
+ eventTypeCount: ALL_EVENT_TYPES.length,
326
+ });
327
+ };
328
+
329
+ const statusChanged: string =
330
+ ServiceLevelObjectiveFeedEventType.StatusChanged;
331
+
332
+ render(<SloFeed sloId={SLO_ID} />);
333
+
334
+ await waitFor(() => {
335
+ expect(
336
+ screen.getByText("No activity has been recorded for this SLO yet."),
337
+ ).toBeInTheDocument();
338
+ });
339
+
340
+ /*
341
+ * The button is named by its visible label alone; what the feed is
342
+ * showing is read out as its description, so a screen reader says each
343
+ * once.
344
+ */
345
+ const optionsButton: HTMLElement = screen.getByRole("button", {
346
+ name: "Filter & Sort",
347
+ });
348
+
349
+ expect(optionsButton).toHaveAccessibleDescription(
350
+ getExpectedSummary(DEFAULT_FEED_OPTIONS),
351
+ );
352
+
353
+ fireEvent.click(optionsButton);
354
+
355
+ const panel: HTMLElement = screen.getByRole("dialog", {
356
+ name: FEED_OPTIONS_TEXT.panelLabel,
357
+ });
358
+
359
+ // StatusChanged is one of the SLO's own events, not a shared one.
360
+ fireEvent.click(
361
+ within(panel).getByTestId(`feed-options-event-type-${statusChanged}`),
362
+ );
363
+
364
+ await waitFor(() => {
365
+ expect(mockGetListCalls).toHaveLength(2);
366
+ });
367
+
368
+ const request: GetListRequest = mockGetListCalls[1]!;
369
+ const query: Record<string, unknown> = request["query"] as Record<
370
+ string,
371
+ unknown
372
+ >;
373
+ const eventTypeFilter: unknown =
374
+ query["serviceLevelObjectiveFeedEventType"];
375
+
376
+ expect(Object.keys(query).sort()).toEqual(
377
+ ["serviceLevelObjectiveId", "serviceLevelObjectiveFeedEventType"].sort(),
378
+ );
379
+ expect(query["serviceLevelObjectiveId"]).toBe(SLO_ID);
380
+ expect(eventTypeFilter).toBeInstanceOf(Includes);
381
+ expect((eventTypeFilter as Includes).values).toEqual([statusChanged]);
382
+ expect(request["sort"]).toEqual({ postedAt: SortOrder.Descending });
383
+
384
+ // The name stays put with a count on the button; the description moves.
385
+ expect(
386
+ screen.getByRole("button", { name: "Filter & Sort" }),
387
+ ).toHaveAccessibleDescription(
388
+ getExpectedSummary({
389
+ sortOrder: SortOrder.Descending,
390
+ eventTypes: [statusChanged],
391
+ }),
392
+ );
393
+ });
289
394
  });
@@ -0,0 +1,566 @@
1
+ import {
2
+ afterEach,
3
+ beforeEach,
4
+ describe,
5
+ expect,
6
+ jest,
7
+ test,
8
+ } from "@jest/globals";
9
+ import {
10
+ cleanup,
11
+ render,
12
+ screen,
13
+ waitFor,
14
+ within,
15
+ } from "@testing-library/react";
16
+ import userEvent from "@testing-library/user-event";
17
+ import React from "react";
18
+ import getSloMonitorRuleFormFields from "../../../../App/FeatureSet/Dashboard/src/Pages/Slo/View/SloMonitorRuleFormFields";
19
+ import ServiceLevelObjectiveMonitorRule from "../../../Models/DatabaseModels/ServiceLevelObjectiveMonitorRule";
20
+ import FilterCondition from "../../../Types/Filter/FilterCondition";
21
+ import MonitorType from "../../../Types/Monitor/MonitorType";
22
+ import ObjectID from "../../../Types/ObjectID";
23
+ import Permission from "../../../Types/Permission";
24
+ import RuleCriteria, {
25
+ RULE_CRITERIA_LEGACY_NEVER_MATCH_PATTERN,
26
+ RULE_CRITERIA_SCHEMA_VERSION,
27
+ RuleCriteriaOperator,
28
+ } from "../../../Types/Rules/RuleCriteria";
29
+ import ModelForm, { FormType } from "../../../UI/Components/Forms/ModelForm";
30
+ import { getLegacyRuleCriteriaFields } from "../../../UI/Components/RuleCriteria/RuleCriteriaModelForm";
31
+ import { getRuleCriteriaSummaryText } from "../../../UI/Components/RuleCriteria/RuleCriteriaSummary";
32
+
33
+ /*
34
+ * Drive the real ModelForm and dropdowns using the SLO page's actual fields.
35
+ * This catches fields being removed by column permissions, builder conversion,
36
+ * edit loading, and serialization, not just the labels in the configuration.
37
+ */
38
+ let savedRule: ServiceLevelObjectiveMonitorRule | null = null;
39
+ let submittedRule: ServiceLevelObjectiveMonitorRule | null = null;
40
+ let selectedFields: Record<string, unknown> = {};
41
+ let permissions: Array<Permission> = [];
42
+
43
+ jest.mock("../../../UI/Utils/Permission", () => {
44
+ return {
45
+ __esModule: true,
46
+ default: {
47
+ getAllPermissions: (): Array<Permission> => {
48
+ return permissions;
49
+ },
50
+ getProjectPermissions: (): null => {
51
+ return null;
52
+ },
53
+ getGlobalPermissions: (): { globalPermissions: Array<Permission> } => {
54
+ return { globalPermissions: permissions };
55
+ },
56
+ },
57
+ };
58
+ });
59
+
60
+ jest.mock("../../../UI/Utils/User", () => {
61
+ return {
62
+ __esModule: true,
63
+ default: {
64
+ isMasterAdmin: (): boolean => {
65
+ return false;
66
+ },
67
+ getUserId: (): null => {
68
+ return null;
69
+ },
70
+ },
71
+ };
72
+ });
73
+
74
+ jest.mock("../../../UI/Utils/Translation", () => {
75
+ return {
76
+ __esModule: true,
77
+ default: () => {
78
+ return {
79
+ translateString: (value: string | undefined): string | undefined => {
80
+ return value;
81
+ },
82
+ translateValue: (value: unknown): unknown => {
83
+ return value;
84
+ },
85
+ };
86
+ },
87
+ };
88
+ });
89
+
90
+ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
91
+ return {
92
+ __esModule: true,
93
+ default: {
94
+ getItem: async (data: {
95
+ select: Record<string, unknown>;
96
+ }): Promise<ServiceLevelObjectiveMonitorRule | null> => {
97
+ selectedFields = data.select;
98
+ return savedRule;
99
+ },
100
+ getList: async (): Promise<{
101
+ data: Array<unknown>;
102
+ count: number;
103
+ skip: number;
104
+ limit: number;
105
+ }> => {
106
+ return { data: [], count: 0, skip: 0, limit: 50 };
107
+ },
108
+ getCommonHeaders: (): Record<string, string> => {
109
+ return {};
110
+ },
111
+ createOrUpdate: async (data: {
112
+ model: ServiceLevelObjectiveMonitorRule;
113
+ }): Promise<{ data: ServiceLevelObjectiveMonitorRule }> => {
114
+ submittedRule = data.model;
115
+ return { data: data.model };
116
+ },
117
+ },
118
+ };
119
+ });
120
+
121
+ const RULE_ID: string = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa";
122
+
123
+ function criteriaWith(
124
+ field: string,
125
+ operator: RuleCriteriaOperator,
126
+ value: string,
127
+ ): RuleCriteria {
128
+ return {
129
+ schemaVersion: RULE_CRITERIA_SCHEMA_VERSION,
130
+ filterCondition: FilterCondition.All,
131
+ filters: [{ field: field, operator: operator, value: value }],
132
+ };
133
+ }
134
+
135
+ function existingRule(
136
+ criteria?: RuleCriteria,
137
+ ): ServiceLevelObjectiveMonitorRule {
138
+ const rule: ServiceLevelObjectiveMonitorRule =
139
+ new ServiceLevelObjectiveMonitorRule();
140
+ rule._id = RULE_ID;
141
+ rule.name = "Production API monitors";
142
+ rule.isEnabled = true;
143
+ if (criteria !== undefined) {
144
+ rule.criteria = criteria;
145
+ }
146
+ return rule;
147
+ }
148
+
149
+ async function renderForm(formType: FormType = FormType.Create): Promise<void> {
150
+ render(
151
+ <ModelForm<ServiceLevelObjectiveMonitorRule>
152
+ modelType={ServiceLevelObjectiveMonitorRule}
153
+ id="slo-monitor-rule-form"
154
+ name="SLO Monitor Rule"
155
+ fields={getSloMonitorRuleFormFields()}
156
+ formType={formType}
157
+ modelIdToEdit={
158
+ formType === FormType.Update ? new ObjectID(RULE_ID) : undefined
159
+ }
160
+ initialValues={
161
+ formType === FormType.Create
162
+ ? { name: "Production API monitors", isEnabled: true }
163
+ : undefined
164
+ }
165
+ steps={[
166
+ { title: "Basic Info", id: "basic-info" },
167
+ { title: "Match Criteria", id: "match-criteria" },
168
+ ]}
169
+ submitButtonText="Save SLO Monitor Rule"
170
+ />,
171
+ );
172
+
173
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
174
+ await user.click(await screen.findByRole("button", { name: /Next/i }));
175
+ await screen.findByTestId("rule-criteria-builder");
176
+ }
177
+
178
+ async function selectOption(name: string, label: string): Promise<void> {
179
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
180
+ await user.click(screen.getByRole("combobox", { name: name }));
181
+ const options: Array<HTMLElement> = await screen.findAllByText(label, {
182
+ exact: true,
183
+ });
184
+ await user.click(options[options.length - 1]!);
185
+ }
186
+
187
+ async function addCondition(title: string): Promise<void> {
188
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
189
+ await user.click(screen.getByTestId("rule-criteria-add"));
190
+ const index: number = screen.getAllByText("Criteria", { exact: true }).length;
191
+ await selectOption(`Criteria for condition ${index}`, title);
192
+ }
193
+
194
+ async function submitForm(): Promise<ServiceLevelObjectiveMonitorRule> {
195
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
196
+ await user.click(
197
+ screen.getByRole("button", { name: "Save SLO Monitor Rule" }),
198
+ );
199
+ await waitFor(() => {
200
+ expect(submittedRule).not.toBeNull();
201
+ });
202
+ return submittedRule!;
203
+ }
204
+
205
+ beforeEach(() => {
206
+ savedRule = null;
207
+ submittedRule = null;
208
+ selectedFields = {};
209
+ permissions = [Permission.ProjectOwner, Permission.User];
210
+ });
211
+
212
+ afterEach(() => {
213
+ cleanup();
214
+ });
215
+
216
+ describe("SLO monitor rule criteria in the create and edit forms", () => {
217
+ test("lists Monitor Type and names text fields without Pattern", async () => {
218
+ await renderForm();
219
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
220
+ await user.click(screen.getByTestId("rule-criteria-add"));
221
+ await user.click(
222
+ screen.getByRole("combobox", { name: "Criteria for condition 1" }),
223
+ );
224
+
225
+ for (const title of [
226
+ "Monitor Labels",
227
+ "Monitor Type",
228
+ "Monitor Name",
229
+ "Monitor Description",
230
+ ]) {
231
+ expect(
232
+ screen.getAllByText(title, { exact: true }).length,
233
+ ).toBeGreaterThan(0);
234
+ }
235
+ expect(
236
+ screen.queryByText("Monitor Name Pattern", { exact: true }),
237
+ ).toBeNull();
238
+ expect(
239
+ screen.queryByText("Monitor Description Pattern", { exact: true }),
240
+ ).toBeNull();
241
+ });
242
+
243
+ test("offers every valid monitor type as a single dropdown value", async () => {
244
+ await renderForm();
245
+ await addCondition("Monitor Type");
246
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
247
+ await user.click(
248
+ screen.getByRole("combobox", { name: "Value for condition 1" }),
249
+ );
250
+
251
+ for (const monitorType of Object.values(MonitorType)) {
252
+ expect(screen.getByText(monitorType, { exact: true })).not.toBeNull();
253
+ }
254
+ expect(screen.queryByText("No options")).toBeNull();
255
+
256
+ await user.click(screen.getByText(MonitorType.Website, { exact: true }));
257
+ await selectOption("Value for condition 1", MonitorType.API);
258
+ const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
259
+ expect(rule.criteria).toEqual(
260
+ criteriaWith("monitorType", RuleCriteriaOperator.Equals, MonitorType.API),
261
+ );
262
+ });
263
+
264
+ test("limits Monitor Type operators to Equals and Does not equal", async () => {
265
+ await renderForm();
266
+ await addCondition("Monitor Type");
267
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
268
+ await user.click(
269
+ screen.getByRole("combobox", { name: "Operator for condition 1" }),
270
+ );
271
+
272
+ expect(
273
+ screen.getAllByText("Equals", { exact: true }).length,
274
+ ).toBeGreaterThan(0);
275
+ expect(screen.getByText("Does not equal", { exact: true })).not.toBeNull();
276
+ for (const unsupported of [
277
+ "Contains",
278
+ "Matches pattern",
279
+ "Does not match pattern",
280
+ "Has any of",
281
+ ]) {
282
+ expect(screen.queryByText(unsupported, { exact: true })).toBeNull();
283
+ }
284
+
285
+ await user.click(screen.getByText("Does not equal", { exact: true }));
286
+ await selectOption("Value for condition 1", MonitorType.Manual);
287
+ const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
288
+ expect(rule.criteria).toEqual(
289
+ criteriaWith(
290
+ "monitorType",
291
+ RuleCriteriaOperator.NotEquals,
292
+ MonitorType.Manual,
293
+ ),
294
+ );
295
+ });
296
+
297
+ test.each([
298
+ ["Monitor Name", "monitorNamePattern"],
299
+ ["Monitor Description", "monitorDescriptionPattern"],
300
+ ])(
301
+ "offers pattern operators for %s and preserves its stored field key",
302
+ async (title: string, field: string) => {
303
+ await renderForm();
304
+ await addCondition(title);
305
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
306
+ await user.click(
307
+ screen.getByRole("combobox", { name: "Operator for condition 1" }),
308
+ );
309
+ expect(
310
+ screen.getAllByText("Matches pattern", { exact: true }).length,
311
+ ).toBeGreaterThan(0);
312
+ expect(
313
+ screen.getByText("Does not match pattern", { exact: true }),
314
+ ).not.toBeNull();
315
+ expect(screen.getByText("Contains", { exact: true })).not.toBeNull();
316
+
317
+ await user.click(
318
+ screen.getByText("Does not match pattern", { exact: true }),
319
+ );
320
+ await user.type(
321
+ screen.getByTestId("rule-criteria-value-0"),
322
+ "^staging-.*",
323
+ );
324
+ const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
325
+ expect(rule.criteria).toEqual(
326
+ criteriaWith(
327
+ field,
328
+ RuleCriteriaOperator.DoesNotMatchPattern,
329
+ "^staging-.*",
330
+ ),
331
+ );
332
+ },
333
+ );
334
+
335
+ test.each([FilterCondition.All, FilterCondition.Any])(
336
+ "combines type and text conditions with Match %s and sends the compatibility shadow",
337
+ async (filterCondition: FilterCondition) => {
338
+ await renderForm();
339
+ await addCondition("Monitor Type");
340
+ await selectOption("Value for condition 1", MonitorType.API);
341
+ await addCondition("Monitor Name");
342
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
343
+ await user.type(screen.getByTestId("rule-criteria-value-1"), "api-*");
344
+ await user.click(
345
+ screen.getByTestId(
346
+ filterCondition === FilterCondition.All
347
+ ? "rule-criteria-match-all"
348
+ : "rule-criteria-match-any",
349
+ ),
350
+ );
351
+
352
+ const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
353
+ expect(rule.criteria).toEqual({
354
+ schemaVersion: RULE_CRITERIA_SCHEMA_VERSION,
355
+ filterCondition: filterCondition,
356
+ filters: [
357
+ {
358
+ field: "monitorType",
359
+ operator: RuleCriteriaOperator.Equals,
360
+ value: MonitorType.API,
361
+ },
362
+ {
363
+ field: "monitorNamePattern",
364
+ operator: RuleCriteriaOperator.MatchesPattern,
365
+ value: "api-*",
366
+ },
367
+ ],
368
+ });
369
+ expect(rule.monitorType).toBeNull();
370
+ expect(rule.monitorNamePattern).toBe(
371
+ RULE_CRITERIA_LEGACY_NEVER_MATCH_PATTERN,
372
+ );
373
+ expect(rule.monitorDescriptionPattern).toBeNull();
374
+ expect(rule.monitorLabels).toEqual([]);
375
+ },
376
+ );
377
+
378
+ test("prevents saving a Monitor Type condition without choosing a value", async () => {
379
+ await renderForm();
380
+ await addCondition("Monitor Type");
381
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
382
+ await user.click(
383
+ screen.getByRole("button", { name: "Save SLO Monitor Rule" }),
384
+ );
385
+ expect(
386
+ (await screen.findByTestId("rule-criteria-error")).textContent,
387
+ ).toContain("non-blank");
388
+ expect(submittedRule).toBeNull();
389
+ });
390
+
391
+ test("clears an incompatible pattern when switching to Monitor Type", async () => {
392
+ await renderForm();
393
+ await addCondition("Monitor Name");
394
+ const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
395
+ await user.type(screen.getByTestId("rule-criteria-value-0"), "api-*");
396
+ await selectOption("Criteria for condition 1", "Monitor Type");
397
+
398
+ expect(screen.getByText("Equals", { exact: true })).not.toBeNull();
399
+ expect(screen.queryByDisplayValue("api-*")).toBeNull();
400
+ expect(screen.getByText("Select Monitor Type")).not.toBeNull();
401
+ await selectOption("Value for condition 1", MonitorType.Ping);
402
+ const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
403
+ expect(rule.criteria).toEqual(
404
+ criteriaWith(
405
+ "monitorType",
406
+ RuleCriteriaOperator.Equals,
407
+ MonitorType.Ping,
408
+ ),
409
+ );
410
+ });
411
+
412
+ test.each([
413
+ [RuleCriteriaOperator.Equals, MonitorType.DockerSwarm],
414
+ [RuleCriteriaOperator.NotEquals, MonitorType.SSLCertificate],
415
+ ])(
416
+ "loads and saves a stored type condition using %s without changing it",
417
+ async (operator: RuleCriteriaOperator, monitorType: MonitorType) => {
418
+ const criteria: RuleCriteria = criteriaWith(
419
+ "monitorType",
420
+ operator,
421
+ monitorType,
422
+ );
423
+ savedRule = existingRule(criteria);
424
+ savedRule.monitorNamePattern = RULE_CRITERIA_LEGACY_NEVER_MATCH_PATTERN;
425
+ await renderForm(FormType.Update);
426
+
427
+ expect(selectedFields).toMatchObject({
428
+ monitorType: true,
429
+ criteria: true,
430
+ });
431
+ const row: HTMLElement = screen.getByTestId("rule-criteria-row-0");
432
+ expect(
433
+ within(row).getByText("Monitor Type", { exact: true }),
434
+ ).not.toBeNull();
435
+ expect(
436
+ within(row).getByText(monitorType, { exact: true }),
437
+ ).not.toBeNull();
438
+ expect(
439
+ within(row).getByText(
440
+ operator === RuleCriteriaOperator.Equals
441
+ ? "Equals"
442
+ : "Does not equal",
443
+ { exact: true },
444
+ ),
445
+ ).not.toBeNull();
446
+ const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
447
+ expect(rule._id).toBe(RULE_ID);
448
+ expect(rule.criteria).toEqual(criteria);
449
+ },
450
+ );
451
+
452
+ test("edits a saved type and operator", async () => {
453
+ savedRule = existingRule(
454
+ criteriaWith("monitorType", RuleCriteriaOperator.Equals, MonitorType.API),
455
+ );
456
+ await renderForm(FormType.Update);
457
+ await selectOption("Operator for condition 1", "Does not equal");
458
+ await selectOption("Value for condition 1", MonitorType.Manual);
459
+ const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
460
+ expect(rule.criteria).toEqual(
461
+ criteriaWith(
462
+ "monitorType",
463
+ RuleCriteriaOperator.NotEquals,
464
+ MonitorType.Manual,
465
+ ),
466
+ );
467
+ });
468
+
469
+ test("hydrates legacy name and description patterns under their new labels", async () => {
470
+ savedRule = existingRule();
471
+ savedRule.monitorNamePattern = "^api-";
472
+ savedRule.monitorDescriptionPattern = "*customer*";
473
+ await renderForm(FormType.Update);
474
+
475
+ expect(screen.getByText("Monitor Name", { exact: true })).not.toBeNull();
476
+ expect(
477
+ screen.getByText("Monitor Description", { exact: true }),
478
+ ).not.toBeNull();
479
+ expect(
480
+ screen.getAllByText("Matches pattern", { exact: true }),
481
+ ).toHaveLength(2);
482
+ expect(screen.getByDisplayValue("^api-")).not.toBeNull();
483
+ expect(screen.getByDisplayValue("*customer*")).not.toBeNull();
484
+ const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
485
+ expect(rule.criteria).toEqual({
486
+ schemaVersion: RULE_CRITERIA_SCHEMA_VERSION,
487
+ filterCondition: FilterCondition.All,
488
+ filters: [
489
+ {
490
+ field: "monitorNamePattern",
491
+ operator: RuleCriteriaOperator.MatchesPattern,
492
+ value: "^api-",
493
+ },
494
+ {
495
+ field: "monitorDescriptionPattern",
496
+ operator: RuleCriteriaOperator.MatchesPattern,
497
+ value: "*customer*",
498
+ },
499
+ ],
500
+ });
501
+ });
502
+
503
+ test("hydrates a legacy monitor type using Equals", async () => {
504
+ savedRule = existingRule();
505
+ savedRule.monitorType = MonitorType.Server;
506
+ await renderForm(FormType.Update);
507
+
508
+ expect(screen.getByText("Monitor Type", { exact: true })).not.toBeNull();
509
+ expect(screen.getByText("Equals", { exact: true })).not.toBeNull();
510
+ expect(
511
+ screen.getByText(MonitorType.Server, { exact: true }),
512
+ ).not.toBeNull();
513
+ const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
514
+ expect(rule.criteria).toEqual(
515
+ criteriaWith(
516
+ "monitorType",
517
+ RuleCriteriaOperator.Equals,
518
+ MonitorType.Server,
519
+ ),
520
+ );
521
+ });
522
+
523
+ test("shows Monitor Type to a user with only the specific create permission", async () => {
524
+ permissions = [
525
+ Permission.CreateServiceLevelObjectiveMonitorRule,
526
+ Permission.User,
527
+ ];
528
+ await renderForm();
529
+ await addCondition("Monitor Type");
530
+ await selectOption("Value for condition 1", MonitorType.Website);
531
+ const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
532
+ expect(rule.criteria?.filters[0]?.value).toBe(MonitorType.Website);
533
+ });
534
+
535
+ test("uses concise field names and explicit operators in rule summaries", () => {
536
+ const rule: ServiceLevelObjectiveMonitorRule = existingRule({
537
+ schemaVersion: RULE_CRITERIA_SCHEMA_VERSION,
538
+ filterCondition: FilterCondition.All,
539
+ filters: [
540
+ {
541
+ field: "monitorType",
542
+ operator: RuleCriteriaOperator.Equals,
543
+ value: MonitorType.API,
544
+ },
545
+ {
546
+ field: "monitorNamePattern",
547
+ operator: RuleCriteriaOperator.MatchesPattern,
548
+ value: "api-*",
549
+ },
550
+ {
551
+ field: "monitorDescriptionPattern",
552
+ operator: RuleCriteriaOperator.DoesNotMatchPattern,
553
+ value: "*staging*",
554
+ },
555
+ ],
556
+ });
557
+ expect(
558
+ getRuleCriteriaSummaryText({
559
+ fields: getLegacyRuleCriteriaFields(getSloMonitorRuleFormFields()),
560
+ item: rule,
561
+ }),
562
+ ).toBe(
563
+ "Match all: Monitor Type equals “API”; Monitor Name matches pattern “api-*”; Monitor Description does not match pattern “*staging*”",
564
+ );
565
+ });
566
+ });