@oneuptime/common 12.0.30 → 12.0.31

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 (489) hide show
  1. package/Models/AnalyticsModels/SecurityEvent.ts +48 -16
  2. package/Models/AnalyticsModels/ThreatIntelIndicator.ts +10 -5
  3. package/Models/DatabaseModels/AlertSeverity.ts +44 -0
  4. package/Models/DatabaseModels/DetectionRule.ts +16 -5
  5. package/Models/DatabaseModels/GoogleSecOpsConnection.ts +14 -5
  6. package/Models/DatabaseModels/IncidentSeverity.ts +44 -0
  7. package/Models/DatabaseModels/Index.ts +2 -0
  8. package/Models/DatabaseModels/NetworkDevice.ts +113 -3
  9. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +88 -0
  10. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +22 -0
  11. package/Models/DatabaseModels/NetworkDeviceOidTemplate.ts +499 -0
  12. package/Models/DatabaseModels/ThreatIntelFeed.ts +16 -5
  13. package/Server/API/GlobalConfigAPI.ts +362 -183
  14. package/Server/API/TelemetryAPI.ts +42 -4
  15. package/Server/EnvironmentConfig.ts +112 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.ts +59 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.ts +25 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  19. package/Server/Middleware/MultipartFormData.ts +118 -32
  20. package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +9 -1
  21. package/Server/Services/AlertEpisodeOnCallRuleEngineService.ts +9 -1
  22. package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +9 -1
  23. package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +9 -1
  24. package/Server/Services/AlertGroupingEngineService.ts +9 -1
  25. package/Server/Services/AlertLabelRuleEngineService.ts +9 -1
  26. package/Server/Services/AlertOnCallRuleEngineService.ts +9 -1
  27. package/Server/Services/AlertOwnerRuleEngineService.ts +9 -1
  28. package/Server/Services/AlertPrivacyRuleEngineService.ts +9 -1
  29. package/Server/Services/AlertReminderRuleService.ts +9 -1
  30. package/Server/Services/AutoRemediationRuleEngineService.ts +9 -1
  31. package/Server/Services/CephClusterLabelRuleEngineService.ts +9 -1
  32. package/Server/Services/CephClusterOwnerRuleEngineService.ts +9 -1
  33. package/Server/Services/CloudResourceLabelRuleEngineService.ts +9 -1
  34. package/Server/Services/CloudResourceOwnerRuleEngineService.ts +9 -1
  35. package/Server/Services/DashboardLabelRuleEngineService.ts +9 -1
  36. package/Server/Services/DashboardOwnerRuleEngineService.ts +9 -1
  37. package/Server/Services/DockerHostLabelRuleEngineService.ts +9 -1
  38. package/Server/Services/DockerHostOwnerRuleEngineService.ts +9 -1
  39. package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +9 -1
  40. package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +9 -1
  41. package/Server/Services/HostLabelRuleEngineService.ts +9 -1
  42. package/Server/Services/HostOwnerRuleEngineService.ts +9 -1
  43. package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +9 -1
  44. package/Server/Services/IncidentEpisodeOnCallRuleEngineService.ts +9 -1
  45. package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +9 -1
  46. package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +9 -1
  47. package/Server/Services/IncidentGroupingEngineService.ts +9 -1
  48. package/Server/Services/IncidentLabelRuleEngineService.ts +9 -1
  49. package/Server/Services/IncidentOnCallRuleEngineService.ts +9 -1
  50. package/Server/Services/IncidentOwnerRuleEngineService.ts +9 -1
  51. package/Server/Services/IncidentPrivacyRuleEngineService.ts +9 -1
  52. package/Server/Services/IncidentReminderRuleService.ts +9 -1
  53. package/Server/Services/IncidentSlaRuleService.ts +9 -1
  54. package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +9 -1
  55. package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +9 -1
  56. package/Server/Services/Index.ts +2 -0
  57. package/Server/Services/IoTFleetLabelRuleEngineService.ts +9 -1
  58. package/Server/Services/IoTFleetOwnerRuleEngineService.ts +9 -1
  59. package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +9 -1
  60. package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +9 -1
  61. package/Server/Services/KubernetesResourceService.ts +5 -1
  62. package/Server/Services/MonitorLabelRuleEngineService.ts +9 -1
  63. package/Server/Services/MonitorOwnerRuleEngineService.ts +9 -1
  64. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +35 -0
  65. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +96 -0
  66. package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +9 -1
  67. package/Server/Services/NetworkDeviceOidTemplateService.ts +201 -0
  68. package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +9 -1
  69. package/Server/Services/NetworkDeviceService.ts +209 -1
  70. package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +9 -1
  71. package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +9 -1
  72. package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +9 -1
  73. package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +9 -1
  74. package/Server/Services/PodmanHostLabelRuleEngineService.ts +9 -1
  75. package/Server/Services/PodmanHostOwnerRuleEngineService.ts +9 -1
  76. package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +9 -1
  77. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +9 -1
  78. package/Server/Services/RumApplicationLabelRuleEngineService.ts +9 -1
  79. package/Server/Services/RumApplicationOwnerRuleEngineService.ts +9 -1
  80. package/Server/Services/RunbookLabelRuleEngineService.ts +9 -1
  81. package/Server/Services/RunbookOwnerRuleEngineService.ts +9 -1
  82. package/Server/Services/RunbookRuleEngineService.ts +9 -1
  83. package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +9 -1
  84. package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +9 -1
  85. package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +9 -1
  86. package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +9 -1
  87. package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +9 -1
  88. package/Server/Services/ServiceLabelRuleEngineService.ts +9 -1
  89. package/Server/Services/ServiceOwnerRuleEngineService.ts +9 -1
  90. package/Server/Services/StatusPageLabelRuleEngineService.ts +9 -1
  91. package/Server/Services/StatusPageMonitorRuleEngineService.ts +7 -0
  92. package/Server/Services/StatusPageOwnerRuleEngineService.ts +9 -1
  93. package/Server/Services/TelemetrySourceMapService.ts +266 -23
  94. package/Server/Services/UserService.ts +27 -0
  95. package/Server/Services/WorkflowLabelRuleEngineService.ts +9 -1
  96. package/Server/Services/WorkflowOwnerRuleEngineService.ts +9 -1
  97. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +186 -0
  98. package/Server/Utils/Monitor/CapturedMetricAttributeUtil.ts +245 -0
  99. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +21 -2
  100. package/Server/Utils/Monitor/MonitorMetricUtil.ts +55 -21
  101. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +32 -0
  102. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +15 -2
  103. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +18 -1
  104. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +10 -0
  105. package/Server/Utils/Monitor/SeriesResourceLabels.ts +34 -0
  106. package/Server/Utils/Rules/RuleEngineRuleRead.ts +48 -0
  107. package/Server/Utils/Telemetry/ExceptionSanitizer.ts +14 -1
  108. package/Server/Utils/Telemetry/LogExceptionExtractor.ts +14 -2
  109. package/Server/Utils/Telemetry/SourceMapResolver.ts +16 -5
  110. package/Server/Utils/Telemetry/StackTraceParser.ts +399 -0
  111. package/Tests/App/Dashboard/EventOverlayHook.test.tsx +125 -0
  112. package/Tests/App/Dashboard/HeaderImageAssets.test.tsx +93 -0
  113. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3 -3
  114. package/Tests/App/Dashboard/UserElementEmail.test.tsx +12 -4
  115. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +1 -1
  116. package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +14 -0
  117. package/Tests/Models/DatabaseModels/ModelRegistryInvariants.test.ts +469 -0
  118. package/Tests/Models/SecurityDomainAccessControl.test.ts +429 -0
  119. package/Tests/Server/API/GlobalConfigLicense.test.ts +657 -0
  120. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +84 -6
  121. package/Tests/Server/API/TelemetryResolveStackTraceAPI.test.ts +805 -0
  122. package/Tests/Server/Infrastructure/Postgres/AddOnCallCalendarFeedsMigration.test.ts +32 -7
  123. package/Tests/Server/Middleware/IdentityRateLimit.test.ts +1144 -0
  124. package/Tests/Server/Middleware/MultipartFormData.test.ts +618 -3
  125. package/Tests/Server/Services/MonitorLabelRuleEngineScale.test.ts +520 -0
  126. package/Tests/Server/Services/NetworkDeviceOidTemplateService.test.ts +332 -0
  127. package/Tests/Server/Services/NetworkDeviceOidTemplateWriteGuards.test.ts +409 -0
  128. package/Tests/Server/Services/RuleEngineRuleFetchLimit.test.ts +239 -0
  129. package/Tests/Server/Services/TelemetrySourceMapService.test.ts +1210 -2
  130. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +182 -0
  131. package/Tests/Server/Types/AnalyticsDatabase/SecurityEventModelPermission.test.ts +255 -0
  132. package/Tests/Server/Types/Database/Permissions/ReadBlockPermission.test.ts +212 -0
  133. package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +413 -0
  134. package/Tests/Server/Utils/CodeRepository.test.ts +689 -0
  135. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +495 -0
  136. package/Tests/Server/Utils/ExceptionSanitizer.test.ts +77 -0
  137. package/Tests/Server/Utils/Monitor/CapturedMetricAttributeUtil.test.ts +284 -0
  138. package/Tests/Server/Utils/Monitor/MonitorCustomMetricAttributes.test.ts +503 -0
  139. package/Tests/Server/Utils/Monitor/MonitorTemplatePrototypePollution.test.ts +106 -0
  140. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkLogWritePath.test.ts +33 -4
  141. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +14 -4
  142. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +44 -0
  143. package/Tests/Server/Utils/OpenAPISpec.test.ts +536 -0
  144. package/Tests/Server/Utils/Rules/RuleEngineRuleRead.test.ts +115 -0
  145. package/Tests/Server/Utils/StackTraceParser.test.ts +610 -0
  146. package/Tests/Server/Utils/Telemetry/LogExceptionExtractor.test.ts +0 -0
  147. package/Tests/Server/Utils/Telemetry/SourceMapLimits.test.ts +656 -0
  148. package/Tests/Server/Utils/Telemetry/SourceMapResolver.test.ts +100 -0
  149. package/Tests/Types/Monitor/SnmpMonitor/SnmpOidListUtil.test.ts +454 -0
  150. package/Tests/Types/SecurityRolePermissions.test.ts +193 -0
  151. package/Tests/UI/Components/Charts/AnnotationLayout.test.ts +773 -0
  152. package/Tests/UI/Components/Charts/ChartAnnotationRail.test.tsx +789 -0
  153. package/Tests/UI/Components/Charts/ChartBucketIdentity.test.ts +254 -0
  154. package/Tests/UI/Components/Charts/TimeAnnotation.test.ts +471 -0
  155. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +405 -0
  156. package/Tests/UI/Components/ErrorMessageRefreshControl.test.tsx +83 -0
  157. package/Tests/UI/Components/MarkdownConverters.test.ts +686 -0
  158. package/Tests/UI/Components/ModelTable/BaseModelTableDeleteAndEmptyStates.test.tsx +341 -0
  159. package/Tests/UI/Components/OrderedStatesList.test.tsx +5 -5
  160. package/Tests/UI/Components/PendingProjectInvitations.test.tsx +1 -1
  161. package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +195 -0
  162. package/Tests/UI/Components/XAxis.test.ts +270 -5
  163. package/Tests/UI/Components/XAxisDaylightSaving.test.ts +113 -0
  164. package/Tests/UI/Styles/ChartFocusRing.test.ts +153 -0
  165. package/Tests/UI/Styles/ChartFocusRingCoverage.test.tsx +377 -0
  166. package/Tests/UI/Styles/ThemeStylesheet.ts +162 -0
  167. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +507 -0
  168. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +951 -1
  169. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +238 -0
  170. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +1056 -0
  171. package/Tests/Utils/NetworkDiscovery/ReverseDnsNameUtil.test.ts +882 -0
  172. package/Types/Date.ts +39 -0
  173. package/Types/Monitor/SnmpMonitor/SnmpOidListUtil.ts +333 -0
  174. package/Types/Permission.ts +96 -0
  175. package/Types/Rum/SessionReplay.ts +21 -0
  176. package/Types/Telemetry/SourceMap.ts +8 -0
  177. package/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.tsx +176 -0
  178. package/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.ts +745 -0
  179. package/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.tsx +576 -0
  180. package/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.tsx +204 -0
  181. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +491 -544
  182. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +324 -372
  183. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +487 -540
  184. package/UI/Components/Charts/ChartLibrary/Types/FormattedReferenceRegion.ts +7 -3
  185. package/UI/Components/Charts/ChartLibrary/Types/FormattedTimeReferenceLine.ts +14 -3
  186. package/UI/Components/Charts/Types/ChartEventKind.ts +13 -0
  187. package/UI/Components/Charts/Types/ReferenceRegionProps.ts +6 -0
  188. package/UI/Components/Charts/Types/TimeReferenceLineProps.ts +20 -3
  189. package/UI/Components/Charts/Utils/TimeAnnotation.ts +69 -35
  190. package/UI/Components/Charts/Utils/XAxis.ts +125 -18
  191. package/UI/Components/EditionLabel/EditionLabel.tsx +280 -26
  192. package/UI/Components/ErrorMessage/ErrorMessage.tsx +21 -10
  193. package/UI/Components/Feed/FeedItem.tsx +4 -5
  194. package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -2
  195. package/UI/Components/Header/UserProfile/UserProfile.tsx +1 -2
  196. package/UI/Components/Image/Image.tsx +20 -3
  197. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  198. package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +1 -2
  199. package/UI/Components/ModelTable/BaseModelTable.tsx +150 -24
  200. package/UI/Components/Table/TableHeader.tsx +64 -48
  201. package/UI/Components/Table/TableRow.tsx +13 -3
  202. package/UI/Styles/Theme.css +38 -0
  203. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +271 -0
  204. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +6 -0
  205. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +141 -10
  206. package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +55 -3
  207. package/Utils/NetworkDiscovery/ReverseDnsNameUtil.ts +151 -0
  208. package/Utils/Rules/RuleEngineLimits.ts +32 -0
  209. package/build/dist/Models/AnalyticsModels/SecurityEvent.js +48 -16
  210. package/build/dist/Models/AnalyticsModels/SecurityEvent.js.map +1 -1
  211. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js +10 -5
  212. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js.map +1 -1
  213. package/build/dist/Models/DatabaseModels/AlertSeverity.js +46 -1
  214. package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
  215. package/build/dist/Models/DatabaseModels/DetectionRule.js +16 -5
  216. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  217. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +14 -5
  218. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
  219. package/build/dist/Models/DatabaseModels/IncidentSeverity.js +46 -1
  220. package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
  221. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  222. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  223. package/build/dist/Models/DatabaseModels/NetworkDevice.js +115 -3
  224. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  225. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +88 -0
  226. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  227. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  228. package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js +519 -0
  229. package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js.map +1 -0
  230. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +16 -5
  231. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js.map +1 -1
  232. package/build/dist/Server/API/GlobalConfigAPI.js +293 -176
  233. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  234. package/build/dist/Server/API/TelemetryAPI.js +31 -3
  235. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  236. package/build/dist/Server/EnvironmentConfig.js +83 -0
  237. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  238. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.js +26 -0
  239. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.js.map +1 -0
  240. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.js +14 -0
  241. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.js.map +1 -0
  242. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  243. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  244. package/build/dist/Server/Middleware/MultipartFormData.js +93 -28
  245. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  246. package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +8 -1
  247. package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
  248. package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js +8 -1
  249. package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js.map +1 -1
  250. package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +8 -1
  251. package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
  252. package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +8 -1
  253. package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
  254. package/build/dist/Server/Services/AlertGroupingEngineService.js +8 -1
  255. package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
  256. package/build/dist/Server/Services/AlertLabelRuleEngineService.js +8 -1
  257. package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
  258. package/build/dist/Server/Services/AlertOnCallRuleEngineService.js +8 -1
  259. package/build/dist/Server/Services/AlertOnCallRuleEngineService.js.map +1 -1
  260. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +8 -1
  261. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
  262. package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +8 -1
  263. package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
  264. package/build/dist/Server/Services/AlertReminderRuleService.js +8 -1
  265. package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
  266. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +8 -1
  267. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
  268. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +8 -1
  269. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
  270. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +8 -1
  271. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
  272. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +8 -1
  273. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
  274. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +8 -1
  275. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
  276. package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +8 -1
  277. package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
  278. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +8 -1
  279. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
  280. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +8 -1
  281. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
  282. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +8 -1
  283. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
  284. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +8 -1
  285. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
  286. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +8 -1
  287. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
  288. package/build/dist/Server/Services/HostLabelRuleEngineService.js +8 -1
  289. package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
  290. package/build/dist/Server/Services/HostOwnerRuleEngineService.js +8 -1
  291. package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
  292. package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +8 -1
  293. package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
  294. package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js +8 -1
  295. package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js.map +1 -1
  296. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +8 -1
  297. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
  298. package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +8 -1
  299. package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
  300. package/build/dist/Server/Services/IncidentGroupingEngineService.js +8 -1
  301. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  302. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +8 -1
  303. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
  304. package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js +8 -1
  305. package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js.map +1 -1
  306. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +8 -1
  307. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
  308. package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +8 -1
  309. package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
  310. package/build/dist/Server/Services/IncidentReminderRuleService.js +8 -1
  311. package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
  312. package/build/dist/Server/Services/IncidentSlaRuleService.js +8 -1
  313. package/build/dist/Server/Services/IncidentSlaRuleService.js.map +1 -1
  314. package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +8 -1
  315. package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
  316. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +8 -1
  317. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
  318. package/build/dist/Server/Services/Index.js +2 -0
  319. package/build/dist/Server/Services/Index.js.map +1 -1
  320. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +8 -1
  321. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
  322. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +8 -1
  323. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
  324. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +8 -1
  325. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
  326. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +8 -1
  327. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
  328. package/build/dist/Server/Services/KubernetesResourceService.js +5 -1
  329. package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -1
  330. package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +8 -1
  331. package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
  332. package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +8 -1
  333. package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
  334. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +30 -21
  335. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  336. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +64 -0
  337. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  338. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +8 -1
  339. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
  340. package/build/dist/Server/Services/NetworkDeviceOidTemplateService.js +180 -0
  341. package/build/dist/Server/Services/NetworkDeviceOidTemplateService.js.map +1 -0
  342. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +8 -1
  343. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
  344. package/build/dist/Server/Services/NetworkDeviceService.js +154 -1
  345. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  346. package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +8 -1
  347. package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
  348. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +8 -1
  349. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
  350. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +8 -1
  351. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
  352. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +8 -1
  353. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
  354. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +8 -1
  355. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
  356. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +8 -1
  357. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
  358. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +8 -1
  359. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
  360. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +8 -1
  361. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
  362. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +8 -1
  363. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
  364. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +8 -1
  365. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
  366. package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +8 -1
  367. package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
  368. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +8 -1
  369. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
  370. package/build/dist/Server/Services/RunbookRuleEngineService.js +8 -1
  371. package/build/dist/Server/Services/RunbookRuleEngineService.js.map +1 -1
  372. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +8 -1
  373. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
  374. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +8 -1
  375. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
  376. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +8 -1
  377. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
  378. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +8 -1
  379. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
  380. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +8 -1
  381. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
  382. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +8 -1
  383. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
  384. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +8 -1
  385. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
  386. package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +8 -1
  387. package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
  388. package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +6 -0
  389. package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -1
  390. package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +8 -1
  391. package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
  392. package/build/dist/Server/Services/TelemetrySourceMapService.js +213 -19
  393. package/build/dist/Server/Services/TelemetrySourceMapService.js.map +1 -1
  394. package/build/dist/Server/Services/UserService.js +25 -0
  395. package/build/dist/Server/Services/UserService.js.map +1 -1
  396. package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +8 -1
  397. package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
  398. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +8 -1
  399. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
  400. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +145 -0
  401. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +1 -0
  402. package/build/dist/Server/Utils/Monitor/CapturedMetricAttributeUtil.js +201 -0
  403. package/build/dist/Server/Utils/Monitor/CapturedMetricAttributeUtil.js.map +1 -0
  404. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +19 -2
  405. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  406. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +42 -23
  407. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  408. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +29 -0
  409. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  410. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +11 -2
  411. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
  412. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +16 -1
  413. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  414. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +10 -0
  415. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  416. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +33 -0
  417. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  418. package/build/dist/Server/Utils/Rules/RuleEngineRuleRead.js +37 -0
  419. package/build/dist/Server/Utils/Rules/RuleEngineRuleRead.js.map +1 -0
  420. package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js +12 -1
  421. package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js.map +1 -1
  422. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +14 -2
  423. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
  424. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js +15 -5
  425. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js.map +1 -1
  426. package/build/dist/Server/Utils/Telemetry/StackTraceParser.js +307 -0
  427. package/build/dist/Server/Utils/Telemetry/StackTraceParser.js.map +1 -1
  428. package/build/dist/Types/Date.js +27 -0
  429. package/build/dist/Types/Date.js.map +1 -1
  430. package/build/dist/Types/Monitor/SnmpMonitor/SnmpOidListUtil.js +253 -0
  431. package/build/dist/Types/Monitor/SnmpMonitor/SnmpOidListUtil.js.map +1 -0
  432. package/build/dist/Types/Permission.js +86 -0
  433. package/build/dist/Types/Permission.js.map +1 -1
  434. package/build/dist/Types/Rum/SessionReplay.js +19 -0
  435. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  436. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.js +83 -0
  437. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.js.map +1 -0
  438. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.js +531 -0
  439. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.js.map +1 -0
  440. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.js +264 -0
  441. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.js.map +1 -0
  442. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.js +122 -0
  443. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.js.map +1 -0
  444. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +213 -233
  445. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  446. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +139 -152
  447. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  448. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +212 -232
  449. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  450. package/build/dist/UI/Components/Charts/Types/ChartEventKind.js +14 -0
  451. package/build/dist/UI/Components/Charts/Types/ChartEventKind.js.map +1 -0
  452. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js +57 -28
  453. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js.map +1 -1
  454. package/build/dist/UI/Components/Charts/Utils/XAxis.js +103 -17
  455. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  456. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +198 -23
  457. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  458. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +15 -5
  459. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
  460. package/build/dist/UI/Components/Feed/FeedItem.js +4 -5
  461. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  462. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -2
  463. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  464. package/build/dist/UI/Components/Header/UserProfile/UserProfile.js.map +1 -1
  465. package/build/dist/UI/Components/Image/Image.js +6 -1
  466. package/build/dist/UI/Components/Image/Image.js.map +1 -1
  467. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  468. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  469. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +1 -2
  470. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
  471. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +104 -23
  472. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  473. package/build/dist/UI/Components/Table/TableHeader.js +20 -22
  474. package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
  475. package/build/dist/UI/Components/Table/TableRow.js +13 -4
  476. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  477. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +153 -0
  478. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -0
  479. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  480. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +127 -7
  481. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  482. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +50 -3
  483. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
  484. package/build/dist/Utils/NetworkDiscovery/ReverseDnsNameUtil.js +132 -0
  485. package/build/dist/Utils/NetworkDiscovery/ReverseDnsNameUtil.js.map +1 -0
  486. package/build/dist/Utils/Rules/RuleEngineLimits.js +31 -0
  487. package/build/dist/Utils/Rules/RuleEngineLimits.js.map +1 -0
  488. package/jest.config.json +1 -0
  489. package/package.json +2 -2
@@ -0,0 +1,93 @@
1
+ import "@testing-library/jest-dom";
2
+ import { render, screen } from "@testing-library/react";
3
+ import React from "react";
4
+ import { describe, expect, jest, test } from "@jest/globals";
5
+
6
+ /*
7
+ * The shape esbuild's file-loader actually hands these components: the imported
8
+ * asset inlined as a "data:" URL (Common/UI/esbuild-config.js,
9
+ * createFileLoaderPlugin). Every existing suite that mocks an .svg mocks it as
10
+ * a plain path like "/blank-profile.svg" — which is exactly the shape that does
11
+ * NOT reproduce this bug, and why the whole test suite stayed green while every
12
+ * dashboard and admin page threw on first render.
13
+ *
14
+ * The "//" in the base64 payload is deliberate. Route collapses /+ into a
15
+ * single /, so the tempting "just let Route accept data: URLs" fix would
16
+ * silently corrupt the image — this payload makes that fix fail here too.
17
+ *
18
+ * ONE constant and ONE jest.mock for both assets on purpose: Common's
19
+ * jest.config.json maps every .svg to Tests/__mocks__/styleMock.js, so two
20
+ * jest.mock() calls naming two different .svg paths resolve to the same module
21
+ * and only the last factory would ever register.
22
+ */
23
+ const ASSET_DATA_URL: string = "data:image/svg+xml;base64,////bG9nbw==";
24
+
25
+ jest.mock("../../../UI/Images/logos/OneUptimeSVG/3-transparent.svg", () => {
26
+ return ASSET_DATA_URL;
27
+ });
28
+
29
+ import DashboardLogo from "../../../../App/FeatureSet/Dashboard/src/Components/Header/Logo";
30
+ import AdminDashboardLogo from "../../../../App/FeatureSet/AdminDashboard/src/Components/Header/Logo";
31
+ import Image from "../../../UI/Components/Image/Image";
32
+
33
+ /*
34
+ * Regression cover for the crash that blocked every release from 2026-08-31.
35
+ *
36
+ * b2d2da71e8 taught Route to reject scheme-prefixed strings — correctly, it
37
+ * guards an open-redirect. But these components were laundering an <img> src
38
+ * through Route.fromString() purely to satisfy Image's prop type, and an
39
+ * esbuild-inlined asset src is always "data:"-prefixed. So Route threw during
40
+ * render, React unwound to the error boundary, and the dashboard never painted.
41
+ *
42
+ * An image src is not a Route. What these pin is that the header renders the
43
+ * asset straight through as an <img src>, with no Route in the path.
44
+ */
45
+ describe("header image assets", () => {
46
+ test("the dashboard logo renders the inlined asset as its src", () => {
47
+ render(
48
+ <DashboardLogo
49
+ onClick={() => {
50
+ // no-op: the click target is not what regressed.
51
+ }}
52
+ />,
53
+ );
54
+
55
+ const logo: HTMLElement = screen.getByAltText("OneUptime");
56
+ expect(logo).toHaveAttribute("src", ASSET_DATA_URL);
57
+ });
58
+
59
+ test("the admin dashboard logo renders the inlined asset as its src", () => {
60
+ render(
61
+ <AdminDashboardLogo
62
+ onClick={() => {
63
+ // no-op
64
+ }}
65
+ />,
66
+ );
67
+
68
+ const logo: HTMLElement = screen.getByAltText("OneUptime");
69
+ expect(logo).toHaveAttribute("src", ASSET_DATA_URL);
70
+ });
71
+
72
+ /*
73
+ * Straight at the type misuse rather than at one component: any scheme-
74
+ * prefixed src has to survive <Image>. Before the fix this threw inside
75
+ * Route.fromString at the call sites; now the string reaches <img> untouched.
76
+ */
77
+ test("Image passes a data: URL through to src without validating it", () => {
78
+ render(<Image imageUrl={ASSET_DATA_URL} alt="asset" />);
79
+
80
+ expect(screen.getByAltText("asset")).toHaveAttribute("src", ASSET_DATA_URL);
81
+ });
82
+
83
+ /*
84
+ * An empty src must not fall through to the `file` branch and throw
85
+ * "file or imageUrl required" — it renders an empty <img>, keeping the node
86
+ * (and its test id) in the DOM.
87
+ */
88
+ test("an empty src renders an image rather than throwing", () => {
89
+ render(<Image imageUrl="" alt="empty" data-testid="empty-image" />);
90
+
91
+ expect(screen.getByTestId("empty-image")).toHaveAttribute("src", "");
92
+ });
93
+ });
@@ -1293,7 +1293,7 @@ describe("ResponderReadinessCard", () => {
1293
1293
  expect(
1294
1294
  await screen.findByText("Could not load readiness"),
1295
1295
  ).toBeInTheDocument();
1296
- expect(screen.getByRole("refresh-button")).toBeInTheDocument();
1296
+ expect(screen.getByTestId("refresh-button")).toBeInTheDocument();
1297
1297
  });
1298
1298
 
1299
1299
  test("retrying issues another request", async () => {
@@ -1305,7 +1305,7 @@ describe("ResponderReadinessCard", () => {
1305
1305
 
1306
1306
  const callsBefore: number = getMock.mock.calls.length;
1307
1307
 
1308
- fireEvent.click(screen.getByRole("refresh-button"));
1308
+ fireEvent.click(screen.getByTestId("refresh-button"));
1309
1309
 
1310
1310
  await waitFor((): void => {
1311
1311
  expect(getMock.mock.calls.length).toBeGreaterThan(callsBefore);
@@ -1784,7 +1784,7 @@ describe("On-call readiness page", () => {
1784
1784
  expect(
1785
1785
  await screen.findByText("Could not load readiness"),
1786
1786
  ).toBeInTheDocument();
1787
- expect(screen.getByRole("refresh-button")).toBeInTheDocument();
1787
+ expect(screen.getByTestId("refresh-button")).toBeInTheDocument();
1788
1788
  });
1789
1789
 
1790
1790
  test("the card chrome survives a failed request", async () => {
@@ -4,11 +4,19 @@ import React from "react";
4
4
  import { describe, expect, jest, test } from "@jest/globals";
5
5
 
6
6
  /*
7
- * The bundler turns an .svg import into a URL string; jest's asset mapper
8
- * turns it into {}, which UserElement then feeds to Route.fromString and
9
- * which throws. Hand it the string shape the browser actually gets.
7
+ * The shape esbuild's file-loader actually hands these components: the asset
8
+ * inlined as a "data:" URL (Common/UI/esbuild-config.js createFileLoaderPlugin).
9
+ * jest's asset mapper turns an .svg import into {} instead, so it has to be
10
+ * mocked - but it must be mocked as a data: URL, not as a plain path like
11
+ * "/blank-profile.svg". A plain path is precisely the shape that does NOT
12
+ * reproduce the crash, which is why this suite stayed green while every
13
+ * dashboard page threw.
14
+ *
15
+ * The "//" in the base64 payload is deliberate. Route collapses /+ into a
16
+ * single /, so a "just let Route accept data: URLs" fix would silently corrupt
17
+ * the image - this constant makes that fix fail here too.
10
18
  */
11
- const BLANK_PROFILE_PIC: string = "/blank-profile.svg";
19
+ const BLANK_PROFILE_PIC: string = "data:image/svg+xml;base64,////YXZhdGFy";
12
20
 
13
21
  jest.mock("../../../UI/Images/users/blank-profile.svg", () => {
14
22
  return BLANK_PROFILE_PIC;
@@ -27,7 +27,7 @@ import {
27
27
  * default avatar) and silent in every other suite, so they are pinned here.
28
28
  */
29
29
 
30
- const BLANK_PROFILE_PIC: string = "/blank-profile.svg";
30
+ const BLANK_PROFILE_PIC: string = "data:image/svg+xml;base64,////YXZhdGFy";
31
31
 
32
32
  jest.mock("../../../UI/Images/users/blank-profile.svg", () => {
33
33
  return BLANK_PROFILE_PIC;
@@ -47,6 +47,7 @@ const DOMAIN_PREFIXES: Array<[string, string]> = [
47
47
  ["Monitor", "Monitor"],
48
48
  ["Workflow", "Workflow"],
49
49
  ["Runbook", "Runbook"],
50
+ ["Security", "Security"],
50
51
  ];
51
52
 
52
53
  /*
@@ -63,6 +64,19 @@ const DOMAIN_BY_MODEL: Record<string, string> = {
63
64
  LogSavedView: "Telemetry",
64
65
  MetricSavedView: "Telemetry",
65
66
  TraceSavedView: "Telemetry",
67
+
68
+ /*
69
+ * The whole SIEM, and not one table of it is named for its domain: a Sigma
70
+ * rule, a TAXII subscription and a Chronicle connector. They shipped reading
71
+ * through the Telemetry tiers because they arrived beside logs and traces in
72
+ * ClickHouse, which made "can read every log in the project" and "can read the
73
+ * security events" one decision. Splitting them is what the Security tiers are
74
+ * for, and naming the three models here is what keeps a fourth from quietly
75
+ * shipping back under Telemetry.
76
+ */
77
+ DetectionRule: "Security",
78
+ ThreatIntelFeed: "Security",
79
+ GoogleSecOpsConnection: "Security",
66
80
  };
67
81
 
68
82
  /*
@@ -0,0 +1,469 @@
1
+ import AllModelTypes from "../../../Models/DatabaseModels/Index";
2
+ import AllAnalyticsModelTypes from "../../../Models/AnalyticsModels/Index";
3
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
4
+ import AnalyticsBaseModel from "../../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
5
+ import { describe, expect, it } from "@jest/globals";
6
+
7
+ /*
8
+ * Registry-wide identity invariants.
9
+ *
10
+ * Every entity in the product is declared once, in a decorator block, and
11
+ * added to Models/DatabaseModels/Index.ts by hand. New entities are almost
12
+ * always written by copying the closest existing one, which makes the
13
+ * failure mode here a very specific and very quiet kind: a value that was
14
+ * meant to be changed during the copy and was not.
15
+ *
16
+ * What makes that worth a sweep rather than a review checklist is that the
17
+ * two identity values below are read at runtime by machinery that has no way
18
+ * to notice a collision:
19
+ *
20
+ * - `tableName` is the Postgres table the entity is persisted to. Two models
21
+ * naming one table are two different shapes writing to the same rows.
22
+ * - `crudApiPath` is the route BaseAPI registers CRUD under. Two models
23
+ * naming one path means whichever registers second shadows the first, and
24
+ * an entire entity's API silently answers as another entity.
25
+ *
26
+ * Neither produces an error at startup. Both produce a product that is wrong
27
+ * in a way that looks like a data bug from the outside.
28
+ *
29
+ * The remaining assertions cover the values the generated OpenAPI document
30
+ * and the dashboard read off a model -- a documented model with no
31
+ * description, or no display name, is a hole in the published API reference
32
+ * rather than a crash, which is exactly why nobody notices it.
33
+ *
34
+ * Sweeping every model rather than asserting on a list is the point: a
35
+ * mis-copied value in a model nobody is looking at fails here rather than in
36
+ * production.
37
+ */
38
+
39
+ type ModelType = { new (): BaseModel };
40
+ type AnalyticsModelType = { new (): AnalyticsBaseModel };
41
+
42
+ const MODEL_TYPES: Array<ModelType> = AllModelTypes as Array<ModelType>;
43
+
44
+ const ANALYTICS_MODEL_TYPES: Array<AnalyticsModelType> =
45
+ AllAnalyticsModelTypes as unknown as Array<AnalyticsModelType>;
46
+
47
+ /*
48
+ * A flat snapshot of the declarations, NOT the model instances.
49
+ *
50
+ * The first version of this file kept all 416 constructed models alive for the
51
+ * lifetime of the file, which is a large object graph resident in a Jest
52
+ * worker whose heap ceiling is deliberately tight (see the note in
53
+ * .github/workflows/test.common.yaml: 2 workers x 4 GB, live set peaking near
54
+ * 3.5 GB). This file shares a shard with the isolated-vm SSRF suite, which
55
+ * needs CPU and memory of its own and reports starvation as a script timeout
56
+ * rather than as an out-of-memory.
57
+ *
58
+ * Every assertion below is about scalar declarations, so the instances exist
59
+ * only long enough to read those off and are collectable immediately after.
60
+ */
61
+ interface RegisteredModel {
62
+ className: string;
63
+ tableName: string | null;
64
+ crudApiPath: string | null;
65
+ singularName: string | null;
66
+ pluralName: string | null;
67
+ enableDocumentation: boolean;
68
+ tableDescription: string | null;
69
+ slugifyColumn: string | null;
70
+ saveSlugToColumn: string | null;
71
+ columns: Array<string>;
72
+ }
73
+
74
+ const REGISTERED_MODELS: Array<RegisteredModel> = MODEL_TYPES.map(
75
+ (ModelClass: ModelType): RegisteredModel => {
76
+ const model: BaseModel = new ModelClass();
77
+
78
+ return {
79
+ className: ModelClass.name,
80
+ tableName: model.tableName,
81
+ crudApiPath: model.crudApiPath ? model.crudApiPath.toString() : null,
82
+ singularName: model.singularName,
83
+ pluralName: model.pluralName,
84
+ enableDocumentation: Boolean(model.enableDocumentation),
85
+ tableDescription: model.tableDescription,
86
+ slugifyColumn: model.slugifyColumn,
87
+ saveSlugToColumn: model.saveSlugToColumn,
88
+ columns: model.getTableColumns().columns,
89
+ };
90
+ },
91
+ );
92
+
93
+ /*
94
+ * Collect every class name that claims `key`, so a failure names both sides of
95
+ * the collision rather than only reporting that a count was wrong.
96
+ */
97
+ const groupBy: (
98
+ keyOf: (entry: RegisteredModel) => string | null,
99
+ ) => Array<string> = (
100
+ keyOf: (entry: RegisteredModel) => string | null,
101
+ ): Array<string> => {
102
+ const claimants: Map<string, Array<string>> = new Map();
103
+
104
+ for (const entry of REGISTERED_MODELS) {
105
+ const key: string | null = keyOf(entry);
106
+
107
+ if (!key) {
108
+ continue;
109
+ }
110
+
111
+ claimants.set(key, [...(claimants.get(key) || []), entry.className]);
112
+ }
113
+
114
+ return Array.from(claimants.entries())
115
+ .filter((pair: [string, Array<string>]) => {
116
+ return pair[1].length > 1;
117
+ })
118
+ .map((pair: [string, Array<string>]) => {
119
+ return `${pair[0]}: ${pair[1].join(", ")}`;
120
+ })
121
+ .sort();
122
+ };
123
+
124
+ describe("Database model registry", () => {
125
+ it("registers at least one model", () => {
126
+ /*
127
+ * Guards every sweep below. An Index.ts that resolved to an empty array
128
+ * would make each of them pass vacuously.
129
+ */
130
+ expect(REGISTERED_MODELS.length).toBeGreaterThan(0);
131
+ });
132
+
133
+ it("gives every model a table name", () => {
134
+ const missing: Array<string> = REGISTERED_MODELS.filter(
135
+ (entry: RegisteredModel) => {
136
+ return !entry.tableName;
137
+ },
138
+ ).map((entry: RegisteredModel) => {
139
+ return entry.className;
140
+ });
141
+
142
+ expect(missing).toEqual([]);
143
+ });
144
+
145
+ /*
146
+ * The collision that persists two different shapes into one set of rows.
147
+ */
148
+ it("gives every model its own table", () => {
149
+ expect(
150
+ groupBy((entry: RegisteredModel) => {
151
+ return entry.tableName;
152
+ }),
153
+ ).toEqual([]);
154
+ });
155
+
156
+ /*
157
+ * The collision where one entity's whole API answers as another's, because
158
+ * BaseAPI registers both under the same route and the second wins.
159
+ */
160
+ it("gives every model its own CRUD path", () => {
161
+ expect(
162
+ groupBy((entry: RegisteredModel) => {
163
+ return entry.crudApiPath;
164
+ }),
165
+ ).toEqual([]);
166
+ });
167
+
168
+ it("gives every model a singular and a plural display name", () => {
169
+ const missing: Array<string> = REGISTERED_MODELS.filter(
170
+ (entry: RegisteredModel) => {
171
+ return !entry.singularName || !entry.pluralName;
172
+ },
173
+ ).map((entry: RegisteredModel) => {
174
+ return entry.className;
175
+ });
176
+
177
+ expect(missing).toEqual([]);
178
+ });
179
+
180
+ /*
181
+ * The description is what the generated OpenAPI document publishes as the
182
+ * tag description for the entity. A documented model without one ships a
183
+ * section of the public API reference with no explanation of what it is.
184
+ */
185
+ it("describes every model it publishes documentation for", () => {
186
+ const undescribed: Array<string> = REGISTERED_MODELS.filter(
187
+ (entry: RegisteredModel) => {
188
+ return entry.enableDocumentation && !entry.tableDescription;
189
+ },
190
+ ).map((entry: RegisteredModel) => {
191
+ return entry.className;
192
+ });
193
+
194
+ expect(undescribed).toEqual([]);
195
+ });
196
+
197
+ /*
198
+ * `enableDocumentation` alone publishes nothing: OpenAPIUtil skips any model
199
+ * with no `crudApiPath`, so the pair disagreeing is a model that believes it
200
+ * is documented and is absent from the document.
201
+ */
202
+ it("gives every documented model a CRUD path to document", () => {
203
+ const undocumentable: Array<string> = REGISTERED_MODELS.filter(
204
+ (entry: RegisteredModel) => {
205
+ return entry.enableDocumentation && !entry.crudApiPath;
206
+ },
207
+ ).map((entry: RegisteredModel) => {
208
+ return entry.className;
209
+ });
210
+
211
+ expect(undocumentable).toEqual([]);
212
+ });
213
+
214
+ /*
215
+ * Slug generation reads the source column and writes the destination one BY
216
+ * NAME at save time (DatabaseService.generateSlug), off an object rather
217
+ * than through the schema -- so a name that matches no declared column is a
218
+ * silent misfire rather than an error.
219
+ *
220
+ * Both halves misfire differently and both are live today:
221
+ *
222
+ * - A source that does not exist reads `undefined`, and Slug.getSlug(null)
223
+ * answers with a slug built from Faker.generateName(). The row still gets
224
+ * a unique, non-null slug, so nothing fails -- the slug is simply a
225
+ * random pair of words instead of the object's own name. Incident is the
226
+ * clearest case: it slugifies "name" while its title column is `title`,
227
+ * and its own slug column documents the example
228
+ * "database-connection-failure-in-production", which is a slugified
229
+ * TITLE. Every incident URL in the product is a random name instead.
230
+ *
231
+ * - A destination that does not exist has the slug assigned to a property
232
+ * the table has no column for, and TypeORM drops it on insert. The whole
233
+ * decorator is dead configuration.
234
+ *
235
+ * The fourteen below are pre-existing and are recorded as a baseline rather
236
+ * than fixed here, because each needs its own judgement: the four that mean
237
+ * `title` are a rename, but the nine with no slug column at all are either a
238
+ * missing column (which needs a migration) or a decorator that should be
239
+ * deleted, and picking wrong is a schema change made on a guess.
240
+ *
241
+ * THIS LIST MUST ONLY EVER SHRINK. A new entry means a new misfire; a stale
242
+ * entry means somebody fixed one and this test says so.
243
+ */
244
+ const KNOWN_SLUG_MISFIRES: Array<string> = [
245
+ /*
246
+ * Source should almost certainly be `title` -- each of these has a title
247
+ * column and a real slug column, so the slug lands but is random.
248
+ */
249
+ "Incident.slugifyColumn = name",
250
+ "IncidentTemplate.slugifyColumn = name",
251
+ "ScheduledMaintenance.slugifyColumn = name",
252
+ "ScheduledMaintenanceTemplate.slugifyColumn = name",
253
+
254
+ /* No name column and no title column; the slug source is `domain`. */
255
+ "Domain.slugifyColumn = name",
256
+
257
+ /* Has the source column, but no slug column to write to. */
258
+ "AlertState.saveSlugToColumn = slug",
259
+ "MetricType.saveSlugToColumn = slug",
260
+ "StatusPageAnnouncementTemplate.saveSlugToColumn = slug",
261
+
262
+ /* Neither column exists: the decorator does nothing at all. */
263
+ "MonitorStatusTimeline.slugifyColumn = name",
264
+ "MonitorStatusTimeline.saveSlugToColumn = slug",
265
+ "MonitorTest.slugifyColumn = name",
266
+ "MonitorTest.saveSlugToColumn = slug",
267
+ "StatusPageAnnouncement.slugifyColumn = name",
268
+ "StatusPageAnnouncement.saveSlugToColumn = slug",
269
+ "StatusPagePrivateUser.slugifyColumn = name",
270
+ "StatusPagePrivateUser.saveSlugToColumn = slug",
271
+ "StatusPageResource.slugifyColumn = name",
272
+ "StatusPageResource.saveSlugToColumn = slug",
273
+ "StatusPageSubscriber.slugifyColumn = name",
274
+ "StatusPageSubscriber.saveSlugToColumn = slug",
275
+ ];
276
+
277
+ const findSlugMisfires: () => Array<string> = (): Array<string> => {
278
+ const dangling: Array<string> = [];
279
+
280
+ for (const entry of REGISTERED_MODELS) {
281
+ const columns: Array<string> = entry.columns;
282
+
283
+ const source: string | null = entry.slugifyColumn;
284
+ const destination: string | null = entry.saveSlugToColumn;
285
+
286
+ if (source && !columns.includes(source)) {
287
+ dangling.push(`${entry.className}.slugifyColumn = ${source}`);
288
+ }
289
+
290
+ if (destination && !columns.includes(destination)) {
291
+ dangling.push(`${entry.className}.saveSlugToColumn = ${destination}`);
292
+ }
293
+ }
294
+
295
+ return dangling.sort();
296
+ };
297
+
298
+ it("introduces no new slug column that does not exist", () => {
299
+ const unexpected: Array<string> = findSlugMisfires().filter(
300
+ (misfire: string) => {
301
+ return !KNOWN_SLUG_MISFIRES.includes(misfire);
302
+ },
303
+ );
304
+
305
+ expect(unexpected).toEqual([]);
306
+ });
307
+
308
+ /*
309
+ * The other direction, so the baseline cannot rot: once a misfire is fixed
310
+ * its entry has to come out of the list above.
311
+ */
312
+ it("keeps no stale entry in the known slug misfire list", () => {
313
+ const found: Array<string> = findSlugMisfires();
314
+
315
+ const stale: Array<string> = KNOWN_SLUG_MISFIRES.filter(
316
+ (misfire: string) => {
317
+ return !found.includes(misfire);
318
+ },
319
+ );
320
+
321
+ expect(stale).toEqual([]);
322
+ });
323
+
324
+ /*
325
+ * A model that slugifies a column must have somewhere to put the result.
326
+ * Only the pair together produces a slug; either one alone is dead
327
+ * configuration.
328
+ */
329
+ it("pairs a slug source with a slug destination", () => {
330
+ const unpaired: Array<string> = REGISTERED_MODELS.filter(
331
+ (entry: RegisteredModel) => {
332
+ return Boolean(entry.slugifyColumn) !== Boolean(entry.saveSlugToColumn);
333
+ },
334
+ ).map((entry: RegisteredModel) => {
335
+ return entry.className;
336
+ });
337
+
338
+ expect(unpaired).toEqual([]);
339
+ });
340
+
341
+ it("declares at least one column on every model", () => {
342
+ const empty: Array<string> = REGISTERED_MODELS.filter(
343
+ (entry: RegisteredModel) => {
344
+ return entry.columns.length === 0;
345
+ },
346
+ ).map((entry: RegisteredModel) => {
347
+ return entry.className;
348
+ });
349
+
350
+ expect(empty).toEqual([]);
351
+ });
352
+
353
+ it("starts every CRUD path with a slash", () => {
354
+ const malformed: Array<string> = REGISTERED_MODELS.filter(
355
+ (entry: RegisteredModel) => {
356
+ const path: string | null = entry.crudApiPath;
357
+
358
+ return path !== null && !path.startsWith("/");
359
+ },
360
+ ).map((entry: RegisteredModel) => {
361
+ return entry.className;
362
+ });
363
+
364
+ expect(malformed).toEqual([]);
365
+ });
366
+ });
367
+
368
+ describe("Analytics model registry", () => {
369
+ /* Flattened for the same reason as the database models above. */
370
+ interface RegisteredAnalyticsModel {
371
+ className: string;
372
+ tableName: string | null;
373
+ crudApiPath: string | null;
374
+ columnCount: number;
375
+ }
376
+
377
+ const REGISTERED: Array<RegisteredAnalyticsModel> = ANALYTICS_MODEL_TYPES.map(
378
+ (ModelClass: AnalyticsModelType): RegisteredAnalyticsModel => {
379
+ const model: AnalyticsBaseModel = new ModelClass();
380
+
381
+ return {
382
+ className: ModelClass.name,
383
+ tableName: model.tableName,
384
+ crudApiPath: model.crudApiPath ? model.crudApiPath.toString() : null,
385
+ columnCount: (model.tableColumns || []).length,
386
+ };
387
+ },
388
+ );
389
+
390
+ it("registers at least one analytics model", () => {
391
+ expect(REGISTERED.length).toBeGreaterThan(0);
392
+ });
393
+
394
+ it("gives every analytics model a table name", () => {
395
+ const missing: Array<string> = REGISTERED.filter(
396
+ (entry: RegisteredAnalyticsModel) => {
397
+ return !entry.tableName;
398
+ },
399
+ ).map((entry: RegisteredAnalyticsModel) => {
400
+ return entry.className;
401
+ });
402
+
403
+ expect(missing).toEqual([]);
404
+ });
405
+
406
+ /*
407
+ * The ClickHouse equivalent of the Postgres collision above: two models
408
+ * writing rows of different shapes into one table.
409
+ */
410
+ it("gives every analytics model its own table", () => {
411
+ const claimants: Map<string, Array<string>> = new Map();
412
+
413
+ for (const entry of REGISTERED) {
414
+ const key: string | null = entry.tableName;
415
+
416
+ if (!key) {
417
+ continue;
418
+ }
419
+
420
+ claimants.set(key, [...(claimants.get(key) || []), entry.className]);
421
+ }
422
+
423
+ const collisions: Array<string> = Array.from(claimants.entries())
424
+ .filter((pair: [string, Array<string>]) => {
425
+ return pair[1].length > 1;
426
+ })
427
+ .map((pair: [string, Array<string>]) => {
428
+ return `${pair[0]}: ${pair[1].join(", ")}`;
429
+ });
430
+
431
+ expect(collisions).toEqual([]);
432
+ });
433
+
434
+ it("gives every analytics model its own CRUD path", () => {
435
+ const claimants: Map<string, Array<string>> = new Map();
436
+
437
+ for (const entry of REGISTERED) {
438
+ const key: string | null = entry.crudApiPath;
439
+
440
+ if (!key) {
441
+ continue;
442
+ }
443
+
444
+ claimants.set(key, [...(claimants.get(key) || []), entry.className]);
445
+ }
446
+
447
+ const collisions: Array<string> = Array.from(claimants.entries())
448
+ .filter((pair: [string, Array<string>]) => {
449
+ return pair[1].length > 1;
450
+ })
451
+ .map((pair: [string, Array<string>]) => {
452
+ return `${pair[0]}: ${pair[1].join(", ")}`;
453
+ });
454
+
455
+ expect(collisions).toEqual([]);
456
+ });
457
+
458
+ it("declares at least one column on every analytics model", () => {
459
+ const empty: Array<string> = REGISTERED.filter(
460
+ (entry: RegisteredAnalyticsModel) => {
461
+ return entry.columnCount === 0;
462
+ },
463
+ ).map((entry: RegisteredAnalyticsModel) => {
464
+ return entry.className;
465
+ });
466
+
467
+ expect(empty).toEqual([]);
468
+ });
469
+ });