@oneuptime/common 13.0.8 → 14.0.0

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 (333) hide show
  1. package/Models/AnalyticsModels/AuditLog.ts +23 -15
  2. package/Models/DatabaseModels/GlobalConfig.ts +24 -0
  3. package/Models/DatabaseModels/Monitor.ts +3 -2
  4. package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
  5. package/Scripts/generate-service-worker.js +65 -4
  6. package/Server/API/BaseAPI.ts +26 -5
  7. package/Server/API/GlobalConfigAPI.ts +228 -462
  8. package/Server/API/ProjectOIDC.ts +25 -16
  9. package/Server/API/ProjectSSO.ts +24 -16
  10. package/Server/API/StatusPageAPI.ts +100 -42
  11. package/Server/API/TeamMemberAPI.ts +10 -1
  12. package/Server/Enterprise/EnterpriseEdition.ts +649 -0
  13. package/Server/Enterprise/EnterpriseFeature.ts +48 -0
  14. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
  15. package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
  16. package/Server/EnvironmentConfig.ts +147 -2
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  19. package/Server/Middleware/UserAuthorization.ts +38 -16
  20. package/Server/Services/AuditLogService.ts +84 -1079
  21. package/Server/Services/EnterpriseLicenseService.ts +38 -0
  22. package/Server/Services/GlobalConfigService.ts +80 -1
  23. package/Server/Services/MonitorProbeService.ts +116 -20
  24. package/Server/Services/MonitorService.ts +56 -4
  25. package/Server/Services/MonitorStatusTimelineService.ts +284 -0
  26. package/Server/Services/MonitorTemplateService.ts +26 -0
  27. package/Server/Services/ProjectService.ts +284 -0
  28. package/Server/Services/RumSessionPinService.ts +25 -6
  29. package/Server/Services/StatusPagePrivateUserService.ts +7 -3
  30. package/Server/Services/StatusPageService.ts +78 -1
  31. package/Server/Services/TeamMemberService.ts +11 -0
  32. package/Server/Services/TeamService.ts +10 -0
  33. package/Server/Services/UserService.ts +10 -17
  34. package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
  35. package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
  36. package/Server/Types/Database/Permissions/TablePermission.ts +10 -3
  37. package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
  38. package/Server/Types/Markdown.ts +41 -0
  39. package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
  40. package/Server/Utils/EditionEnforcement.ts +233 -0
  41. package/Server/Utils/FrontendEnvironment.ts +41 -2
  42. package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
  43. package/Server/Utils/Monitor/AffectedResourceList.ts +190 -0
  44. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
  45. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +543 -333
  46. package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
  47. package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
  48. package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
  49. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
  50. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
  51. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
  52. package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
  53. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
  54. package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
  55. package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
  56. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
  57. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
  58. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
  59. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
  60. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +45 -9
  61. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
  62. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
  63. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -83
  64. package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
  65. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
  66. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
  67. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
  68. package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
  69. package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
  70. package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
  71. package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
  72. package/Tests/Server/API/GlobalConfigLicense.test.ts +742 -497
  73. package/Tests/Server/API/OnCallReadinessAPI.test.ts +35 -909
  74. package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
  75. package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
  76. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
  77. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
  78. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
  79. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
  80. package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
  81. package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
  82. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
  83. package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
  84. package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
  85. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
  86. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
  87. package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
  88. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
  89. package/Tests/Server/Services/AuditLogService.test.ts +460 -990
  90. package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
  91. package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
  92. package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
  93. package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
  94. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
  95. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
  96. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
  97. package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
  98. package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
  99. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
  100. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
  101. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
  102. package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
  103. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
  104. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
  105. package/Tests/Server/Types/Markdown.test.ts +181 -0
  106. package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
  107. package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
  108. package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
  109. package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
  110. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
  111. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
  112. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +934 -96
  113. package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
  114. package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
  115. package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
  116. package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
  117. package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
  118. package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
  119. package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
  120. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +84 -178
  121. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
  122. package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
  123. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
  124. package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
  125. package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
  126. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
  127. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
  128. package/Tests/Utils/HostAddressUtil.test.ts +138 -0
  129. package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
  130. package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
  131. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
  132. package/Types/API/Hostname.ts +63 -16
  133. package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
  134. package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
  135. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
  136. package/Types/Database/CanonicalModelInstance.ts +102 -0
  137. package/Types/Database/TableColumn.ts +20 -6
  138. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
  139. package/Types/IP/IPv6.ts +6 -1
  140. package/Types/Monitor/MonitorStep.ts +6 -1
  141. package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
  142. package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
  143. package/UI/Components/EditionLabel/EditionLabel.tsx +796 -1195
  144. package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
  145. package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
  146. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  147. package/UI/Components/ModelList/ModelList.tsx +11 -1
  148. package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
  149. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
  150. package/UI/esbuild-enterprise.js +263 -0
  151. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
  152. package/Utils/HostAddressUtil.ts +94 -0
  153. package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
  154. package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
  155. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
  156. package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
  157. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  158. package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
  159. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  160. package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
  161. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  162. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
  163. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  164. package/build/dist/Server/API/BaseAPI.js +26 -5
  165. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  166. package/build/dist/Server/API/GlobalConfigAPI.js +148 -344
  167. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  168. package/build/dist/Server/API/ProjectOIDC.js +24 -16
  169. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  170. package/build/dist/Server/API/ProjectSSO.js +24 -16
  171. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  172. package/build/dist/Server/API/StatusPageAPI.js +93 -43
  173. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  174. package/build/dist/Server/API/TeamMemberAPI.js +8 -1
  175. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  176. package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
  177. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
  178. package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
  179. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
  180. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
  181. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
  182. package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
  183. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
  184. package/build/dist/Server/EnvironmentConfig.js +84 -2
  185. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  186. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
  187. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
  188. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  189. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  190. package/build/dist/Server/Middleware/UserAuthorization.js +30 -11
  191. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  192. package/build/dist/Server/Services/AuditLogService.js +71 -740
  193. package/build/dist/Server/Services/AuditLogService.js.map +1 -1
  194. package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
  195. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  196. package/build/dist/Server/Services/GlobalConfigService.js +63 -0
  197. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  198. package/build/dist/Server/Services/MonitorProbeService.js +90 -17
  199. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  200. package/build/dist/Server/Services/MonitorService.js +45 -4
  201. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  202. package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
  203. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  204. package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
  205. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  206. package/build/dist/Server/Services/ProjectService.js +214 -0
  207. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  208. package/build/dist/Server/Services/RumSessionPinService.js +24 -6
  209. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  210. package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
  211. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  212. package/build/dist/Server/Services/StatusPageService.js +71 -0
  213. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  214. package/build/dist/Server/Services/TeamMemberService.js +10 -0
  215. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  216. package/build/dist/Server/Services/TeamService.js +9 -0
  217. package/build/dist/Server/Services/TeamService.js.map +1 -1
  218. package/build/dist/Server/Services/UserService.js +10 -16
  219. package/build/dist/Server/Services/UserService.js.map +1 -1
  220. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
  221. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  222. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
  223. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  224. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +10 -3
  225. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  226. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
  227. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  228. package/build/dist/Server/Types/Markdown.js +31 -0
  229. package/build/dist/Server/Types/Markdown.js.map +1 -1
  230. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
  231. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
  232. package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
  233. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
  234. package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
  235. package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
  236. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
  237. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
  238. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +96 -0
  239. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
  240. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  241. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  242. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +449 -261
  243. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  244. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
  245. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
  246. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
  247. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  248. package/build/dist/Types/API/Hostname.js +59 -11
  249. package/build/dist/Types/API/Hostname.js.map +1 -1
  250. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
  251. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
  252. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
  253. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
  254. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
  255. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
  256. package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
  257. package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
  258. package/build/dist/Types/Database/TableColumn.js +19 -6
  259. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  260. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
  261. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
  262. package/build/dist/Types/IP/IPv6.js +6 -1
  263. package/build/dist/Types/IP/IPv6.js.map +1 -1
  264. package/build/dist/Types/Monitor/MonitorStep.js +5 -0
  265. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  266. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
  267. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
  268. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
  269. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +414 -585
  270. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  271. package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
  272. package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
  273. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
  274. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  275. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  276. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  277. package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
  278. package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
  279. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
  280. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  281. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
  282. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  283. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
  284. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  285. package/build/dist/Utils/HostAddressUtil.js +80 -0
  286. package/build/dist/Utils/HostAddressUtil.js.map +1 -0
  287. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
  288. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
  289. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
  290. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
  291. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  292. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
  293. package/jest.config.json +3 -1
  294. package/package.json +1 -1
  295. package/test-setup.sh +103 -34
  296. package/tsconfig.json +13 -0
  297. package/Server/API/EnterpriseLicenseAPI.ts +0 -925
  298. package/Server/API/TeamComplianceAPI.ts +0 -158
  299. package/Server/Middleware/SCIMAuthorization.ts +0 -141
  300. package/Server/Services/TeamComplianceService.ts +0 -733
  301. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
  302. package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
  303. package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
  304. package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
  305. package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +0 -761
  306. package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
  307. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
  308. package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +0 -321
  309. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
  310. package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
  311. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
  312. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
  313. package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
  314. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
  315. package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
  316. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
  317. package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
  318. package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
  319. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
  320. package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
  321. package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
  322. package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
  323. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
  324. package/build/dist/Server/Services/TeamComplianceService.js +0 -537
  325. package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
  326. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
  327. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
  328. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
  329. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
  330. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
  331. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
  332. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
  333. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
@@ -0,0 +1,254 @@
1
+ import "@testing-library/jest-dom";
2
+ import {
3
+ afterEach,
4
+ beforeEach,
5
+ describe,
6
+ expect,
7
+ jest,
8
+ test,
9
+ } from "@jest/globals";
10
+ import { act, cleanup, render } from "@testing-library/react";
11
+ import React, { ReactElement } from "react";
12
+ import fs from "fs";
13
+ import path from "path";
14
+
15
+ /*
16
+ * The core Header (Admin Dashboard) and Footer (Dashboard) hand their edition
17
+ * pill the Enterprise plugin's LicenseManager, read from the plugin door
18
+ * inside render. With the Community stub - which is what this jest config
19
+ * resolves the plugin specifiers to - they hand it nothing, and the pill
20
+ * shows the license status only.
21
+ *
22
+ * EditionLabel is replaced with a probe that records the prop, and each door
23
+ * with one that returns whatever the test sets (the real Community stub by
24
+ * default). This is core, and must pass with ee/ deleted.
25
+ */
26
+
27
+ const receivedManagers: Array<unknown> = [];
28
+
29
+ jest.mock("../../../UI/Components/EditionLabel/EditionLabel", () => {
30
+ return {
31
+ __esModule: true,
32
+ default: (props: { licenseManager?: unknown }): ReactElement => {
33
+ receivedManagers.push(props.licenseManager);
34
+
35
+ return <span data-testid="edition-label" />;
36
+ },
37
+ };
38
+ });
39
+
40
+ jest.mock("../../../UI/Images/logos/OneUptimeSVG/3-transparent.svg", () => {
41
+ return "data:image/svg+xml;base64,bG9nbw==";
42
+ });
43
+
44
+ jest.mock("react-i18next", () => {
45
+ return {
46
+ useTranslation: () => {
47
+ return {
48
+ t: (key: string): string => {
49
+ return key;
50
+ },
51
+ };
52
+ },
53
+ };
54
+ });
55
+
56
+ jest.mock("../../../UI/Utils/User", () => {
57
+ return {
58
+ __esModule: true,
59
+ default: {
60
+ isMasterAdmin: (): boolean => {
61
+ return true;
62
+ },
63
+ isLoggedIn: (): boolean => {
64
+ return true;
65
+ },
66
+ },
67
+ };
68
+ });
69
+
70
+ jest.mock(
71
+ "../../../../App/FeatureSet/Dashboard/src/Components/LanguageSwitcher/LanguageSwitcher",
72
+ () => {
73
+ return {
74
+ __esModule: true,
75
+ default: (): ReactElement => {
76
+ return <span data-testid="language-switcher" />;
77
+ },
78
+ };
79
+ },
80
+ );
81
+
82
+ let mockAdminPlugins: Record<string, unknown> = {};
83
+ let mockDashboardPlugins: Record<string, unknown> = {};
84
+ let adminDoorReads: number = 0;
85
+ let dashboardDoorReads: number = 0;
86
+
87
+ jest.mock(
88
+ "../../../../App/FeatureSet/AdminDashboard/src/Enterprise/Plugins",
89
+ () => {
90
+ return {
91
+ getAdminDashboardPlugins: (): Record<string, unknown> => {
92
+ adminDoorReads += 1;
93
+ return mockAdminPlugins;
94
+ },
95
+ };
96
+ },
97
+ );
98
+
99
+ jest.mock("../../../../App/FeatureSet/Dashboard/src/Enterprise/Plugins", () => {
100
+ return {
101
+ getDashboardPlugins: (): Record<string, unknown> => {
102
+ dashboardDoorReads += 1;
103
+ return mockDashboardPlugins;
104
+ },
105
+ };
106
+ });
107
+
108
+ import AdminCommunityPlugins from "../../../../App/FeatureSet/AdminDashboard/src/Enterprise/CommunityPlugins";
109
+ import DashboardCommunityPlugins from "../../../../App/FeatureSet/Dashboard/src/Enterprise/CommunityPlugins";
110
+ import AdminDashboardHeader from "../../../../App/FeatureSet/AdminDashboard/src/Components/Header/Header";
111
+ import DashboardFooter from "../../../../App/FeatureSet/Dashboard/src/Components/Footer/Footer";
112
+ import { ADMIN_DASHBOARD_ENTERPRISE_PLUGIN_KEYS } from "../../../../App/FeatureSet/AdminDashboard/src/Enterprise/EnterprisePlugins";
113
+ import { DASHBOARD_ENTERPRISE_PLUGIN_KEYS } from "../../../../App/FeatureSet/Dashboard/src/Enterprise/EnterprisePlugins";
114
+
115
+ const FakeAdminLicenseManager: () => ReactElement = (): ReactElement => {
116
+ return <span />;
117
+ };
118
+
119
+ const FakeDashboardLicenseManager: () => ReactElement = (): ReactElement => {
120
+ return <span />;
121
+ };
122
+
123
+ const APP_DIR: string = path.resolve(__dirname, "..", "..", "..", "..", "App");
124
+
125
+ interface Caller {
126
+ name: string;
127
+ file: string;
128
+ render: () => void;
129
+ setPlugins: (plugins: Record<string, unknown>) => void;
130
+ communityStub: Record<string, unknown>;
131
+ fake: () => ReactElement;
132
+ doorReads: () => number;
133
+ }
134
+
135
+ const CALLERS: Array<Caller> = [
136
+ {
137
+ name: "the Admin Dashboard header",
138
+ file: path.join(
139
+ APP_DIR,
140
+ "FeatureSet/AdminDashboard/src/Components/Header/Header.tsx",
141
+ ),
142
+ render: (): void => {
143
+ render(<AdminDashboardHeader />);
144
+ },
145
+ setPlugins: (plugins: Record<string, unknown>): void => {
146
+ mockAdminPlugins = plugins;
147
+ },
148
+ communityStub: AdminCommunityPlugins as Record<string, unknown>,
149
+ fake: FakeAdminLicenseManager,
150
+ doorReads: (): number => {
151
+ return adminDoorReads;
152
+ },
153
+ },
154
+ {
155
+ name: "the Dashboard footer",
156
+ file: path.join(
157
+ APP_DIR,
158
+ "FeatureSet/Dashboard/src/Components/Footer/Footer.tsx",
159
+ ),
160
+ render: (): void => {
161
+ render(<DashboardFooter />);
162
+ },
163
+ setPlugins: (plugins: Record<string, unknown>): void => {
164
+ mockDashboardPlugins = plugins;
165
+ },
166
+ communityStub: DashboardCommunityPlugins as Record<string, unknown>,
167
+ fake: FakeDashboardLicenseManager,
168
+ doorReads: (): number => {
169
+ return dashboardDoorReads;
170
+ },
171
+ },
172
+ ];
173
+
174
+ beforeEach(() => {
175
+ receivedManagers.length = 0;
176
+ adminDoorReads = 0;
177
+ dashboardDoorReads = 0;
178
+ mockAdminPlugins = AdminCommunityPlugins as Record<string, unknown>;
179
+ mockDashboardPlugins = DashboardCommunityPlugins as Record<string, unknown>;
180
+ });
181
+
182
+ afterEach(() => {
183
+ cleanup();
184
+ });
185
+
186
+ describe("LicenseManager is a key of both plugin contracts", () => {
187
+ test("the Admin Dashboard's", () => {
188
+ expect(ADMIN_DASHBOARD_ENTERPRISE_PLUGIN_KEYS).toContain("LicenseManager");
189
+ });
190
+
191
+ test("the Dashboard's", () => {
192
+ expect(DASHBOARD_ENTERPRISE_PLUGIN_KEYS).toContain("LicenseManager");
193
+ });
194
+
195
+ test("and neither Community stub provides it", () => {
196
+ expect(
197
+ (AdminCommunityPlugins as Record<string, unknown>)["LicenseManager"],
198
+ ).toBeUndefined();
199
+ expect(
200
+ (DashboardCommunityPlugins as Record<string, unknown>)["LicenseManager"],
201
+ ).toBeUndefined();
202
+ });
203
+ });
204
+
205
+ describe.each(CALLERS)("$name", (caller: Caller) => {
206
+ test("passes the plugin's LicenseManager to the edition pill", async () => {
207
+ caller.setPlugins({ LicenseManager: caller.fake });
208
+
209
+ await act(async () => {
210
+ caller.render();
211
+ });
212
+
213
+ expect(receivedManagers).toContain(caller.fake);
214
+ expect(
215
+ receivedManagers.every((value: unknown): boolean => {
216
+ return value === caller.fake;
217
+ }),
218
+ ).toBe(true);
219
+ });
220
+
221
+ test("passes nothing with the Community stub (negative control)", async () => {
222
+ caller.setPlugins(caller.communityStub);
223
+
224
+ await act(async () => {
225
+ caller.render();
226
+ });
227
+
228
+ expect(receivedManagers.length).toBeGreaterThan(0);
229
+ expect(
230
+ receivedManagers.every((value: unknown): boolean => {
231
+ return value === undefined;
232
+ }),
233
+ ).toBe(true);
234
+ });
235
+
236
+ test("reads the door while rendering, not when the module loads", async () => {
237
+ // The module was imported above; no render has happened yet.
238
+ expect(caller.doorReads()).toBe(0);
239
+
240
+ await act(async () => {
241
+ caller.render();
242
+ });
243
+
244
+ expect(caller.doorReads()).toBeGreaterThan(0);
245
+ });
246
+
247
+ test("names the prop in its source, so the wiring is not a coincidence", () => {
248
+ const source: string = fs.readFileSync(caller.file, "utf8");
249
+
250
+ expect(source).toMatch(
251
+ /licenseManager=\{get(AdminDashboard|Dashboard)Plugins\(\)\.LicenseManager\}/,
252
+ );
253
+ });
254
+ });
@@ -14,23 +14,22 @@ import React from "react";
14
14
  import { beforeEach, describe, expect, it } from "@jest/globals";
15
15
 
16
16
  /*
17
- * The "Refresh license" button, and who is allowed to see it.
17
+ * What EditionLabel on its own still does around the license GET and the seat
18
+ * figures, with no license manager (the login page, a build without the
19
+ * Enterprise plugin). This suite must pass with ee/ deleted.
18
20
  *
19
- * The seat limit is set on oneuptime.com and can change on any day. It reaches
20
- * a self-hosted installation through a job that runs once a day — which was
21
- * merely slow while nothing acted on the number, and is a real problem now that
22
- * the installation refuses users above it. An administrator who has just bought
23
- * ten seats should not have to wait until tomorrow, and should not have to
24
- * re-type the license key into a box the dialog hides while the license is
25
- * valid. This button is the answer, so these tests pin that it:
21
+ * The "Refresh license" button this suite used to cover - offered only to a
22
+ * master admin, sending no key, showing the new limit, reporting a failure -
23
+ * is the Enterprise plugin's license manager now, together with the seat
24
+ * card. ee/Tests/UI/License/LicenseManagerRefresh.test.tsx runs every one of
25
+ * this suite's original tests against EditionLabel with that manager. What
26
+ * stays here:
26
27
  *
27
- * - is offered only to a master admin, matching the server, which now
28
- * requires one on both license writes;
29
- * - sends no license key, so it can only ever refresh the key already
30
- * stored and never replace a working license with a typo;
31
- * - shows the new limit afterwards;
32
- * - says so when it fails, rather than looking like it worked. The whole
33
- * reason it was pressed is a belief that the stored terms are stale.
28
+ * - the signedIn flag on the license GET;
29
+ * - a non-admin is told who can activate the license;
30
+ * - EditionLabel never offers a refresh, a key change or the seat card by
31
+ * itself, and writes nothing;
32
+ * - the pill still reads the seat figures, enforced usage first.
34
33
  */
35
34
 
36
35
  let isEnterpriseEdition: boolean = true;
@@ -137,7 +136,14 @@ const licensePayload: LicensePayloadFunction = (
137
136
  expiresAt: EXPIRES_AT,
138
137
  licenseKey: "acme-license-key",
139
138
  token: "signed.jwt.token",
139
+ edition: "enterprise",
140
+ status: "valid",
141
+ verification: "verified",
142
+ graceReason: null,
143
+ graceEndsAt: null,
144
+ activationMode: "online",
140
145
  licenseValid: true,
146
+ isEvaluation: false,
141
147
  isEvaluationLicense: false,
142
148
  userLimit: 50,
143
149
  currentUserCount: 50,
@@ -245,7 +251,14 @@ describe("EditionLabel - telling the license route we expect to be signed in", (
245
251
  });
246
252
  });
247
253
 
248
- describe("EditionLabel - refreshing the license", () => {
254
+ /*
255
+ * Refreshing the license, changing its key and the seat card are the
256
+ * Enterprise plugin's license manager now (ee/Tests/UI/License runs this
257
+ * suite's original refresh and seat tests against it). What EditionLabel
258
+ * still owns is below: telling a non-admin who can act, reading the seat
259
+ * figures for the pill, and never writing the license itself.
260
+ */
261
+ describe("EditionLabel - the license, read-only", () => {
249
262
  beforeEach(() => {
250
263
  fetchCalls.length = 0;
251
264
  isEnterpriseEdition = true;
@@ -257,39 +270,12 @@ describe("EditionLabel - refreshing the license", () => {
257
270
  };
258
271
  });
259
272
 
260
- it("offers the button to a master admin once the license is valid", async () => {
261
- await openDialog();
262
-
263
- expect(
264
- await screen.findByTestId("refresh-enterprise-license"),
265
- ).toBeInTheDocument();
266
- });
267
-
268
- /*
269
- * The server requires a master admin on both license writes, so offering the
270
- * button to anyone else would only ever produce a permission error.
271
- */
272
- it("does not offer the button to a user who is not a master admin", async () => {
273
- isMasterAdmin = false;
274
-
275
- await openDialog();
276
-
277
- await waitFor(() => {
278
- expect(screen.getByText("Licensed seats")).toBeInTheDocument();
279
- });
280
-
281
- expect(
282
- screen.queryByTestId("refresh-enterprise-license"),
283
- ).not.toBeInTheDocument();
284
- expect(screen.queryByText("Change license key")).not.toBeInTheDocument();
285
- });
286
-
287
273
  it("asks a non-admin to find one when the license needs activating", async () => {
288
274
  isMasterAdmin = false;
289
275
  respond = (): HTTPResponse<JSONObject> => {
290
276
  return new HTTPResponse<JSONObject>(
291
277
  200,
292
- licensePayload({ licenseValid: false, token: null }),
278
+ licensePayload({ licenseValid: false, token: null, status: "missing" }),
293
279
  {},
294
280
  );
295
281
  };
@@ -304,95 +290,28 @@ describe("EditionLabel - refreshing the license", () => {
304
290
  ).not.toBeInTheDocument();
305
291
  });
306
292
 
307
- /*
308
- * No license key in the body. A refresh that carried one would be an
309
- * activation with a friendlier name.
310
- */
311
- it("refreshes the stored license without sending a key", async () => {
312
- await openDialog();
313
-
314
- fireEvent.click(await screen.findByTestId("refresh-enterprise-license"));
315
-
316
- await waitFor(() => {
317
- expect(
318
- fetchCalls.some((call: FetchCall): boolean => {
319
- return call.url.includes("/global-config/license/refresh");
320
- }),
321
- ).toBe(true);
322
- });
323
-
324
- const refreshCall: FetchCall = fetchCalls.find(
325
- (call: FetchCall): boolean => {
326
- return call.url.includes("/global-config/license/refresh");
327
- },
328
- ) as FetchCall;
329
-
330
- expect(refreshCall.method).toBe("POST");
331
- expect(refreshCall.data).toBeUndefined();
332
- });
333
-
334
- it("shows the new seat limit after a refresh", async () => {
293
+ it("offers no refresh, key change or seat card on its own, even to a master admin", async () => {
335
294
  await openDialog();
336
295
 
337
- await screen.findByTestId("refresh-enterprise-license");
338
-
339
- // Ten more seats bought on oneuptime.com since the page loaded.
340
- respond = (): HTTPResponse<JSONObject> => {
341
- return new HTTPResponse<JSONObject>(
342
- 200,
343
- licensePayload({
344
- userLimit: 60,
345
- seatsRemaining: 10,
346
- canAddMoreUsers: true,
347
- }),
348
- {},
349
- );
350
- };
351
-
352
- fireEvent.click(screen.getByTestId("refresh-enterprise-license"));
353
-
354
- expect(
355
- await screen.findByText(/License refreshed from OneUptime/),
356
- ).toBeInTheDocument();
357
- expect(await screen.findByText(/60 seats/)).toBeInTheDocument();
358
- });
359
-
360
- /*
361
- * A refresh that quietly kept the old terms and said nothing would be worse
362
- * than no button at all: the administrator pressed it precisely because they
363
- * think the stored terms are wrong.
364
- */
365
- it("reports a failed refresh instead of looking like it worked", async () => {
366
- await openDialog();
367
-
368
- await screen.findByTestId("refresh-enterprise-license");
369
-
370
- respond = (
371
- call: FetchCall,
372
- ): HTTPResponse<JSONObject> | HTTPErrorResponse => {
373
- if (call.url.includes("/refresh")) {
374
- return new HTTPErrorResponse(
375
- 500,
376
- { message: "Could not reach OneUptime." },
377
- {},
378
- );
379
- }
380
-
381
- return new HTTPResponse<JSONObject>(200, licensePayload(), {});
382
- };
383
-
384
- fireEvent.click(screen.getByTestId("refresh-enterprise-license"));
385
-
386
- expect(
387
- await screen.findByText(/Could not reach OneUptime/),
388
- ).toBeInTheDocument();
296
+ expect(await screen.findByText("Licensed to")).toBeInTheDocument();
389
297
  expect(
390
- screen.queryByText(/License refreshed from OneUptime/),
298
+ screen.queryByTestId("refresh-enterprise-license"),
391
299
  ).not.toBeInTheDocument();
300
+ expect(screen.queryByText("Change license key")).not.toBeInTheDocument();
301
+ expect(screen.queryByText("Licensed seats")).not.toBeInTheDocument();
302
+ expect(
303
+ fetchCalls.filter((call: FetchCall): boolean => {
304
+ return call.method !== "GET" || call.url.includes("/refresh");
305
+ }),
306
+ ).toEqual([]);
392
307
  });
393
308
  });
394
309
 
395
- describe("EditionLabel - what an exhausted seat limit looks like", () => {
310
+ /*
311
+ * The pill still reads the seat figures: an exhausted limit is what a master
312
+ * admin has to see on every page, not only inside the dialog.
313
+ */
314
+ describe("EditionLabel - what an exhausted seat limit looks like on the pill", () => {
396
315
  beforeEach(() => {
397
316
  fetchCalls.length = 0;
398
317
  isEnterpriseEdition = true;
@@ -404,64 +323,62 @@ describe("EditionLabel - what an exhausted seat limit looks like", () => {
404
323
  };
405
324
  });
406
325
 
326
+ const pillNamed: (name: string) => Promise<void> = async (
327
+ name: string,
328
+ ): Promise<void> => {
329
+ render(<EditionLabel />);
330
+
331
+ await waitFor(() => {
332
+ expect(
333
+ screen.getByRole("button", { name: /Enterprise Edition/ }),
334
+ ).toHaveAccessibleName(name);
335
+ });
336
+ };
337
+
407
338
  /*
408
- * 50 of 50 is not over the limit, so the old arithmetic called it "nearly
409
- * full" — an amber nudge in front of a door that is already shut. Once the
410
- * limit is enforced, being exactly on it is the thing the administrator has
411
- * to act on.
339
+ * 50 of 50 is not over the limit, but once the limit is enforced nobody
340
+ * else gets in: a breach, not an amber nudge.
412
341
  */
413
- it("treats a full license as a breach rather than a nudge", async () => {
414
- await openDialog();
342
+ it("treats a full enforced license as a breach, on the pill and the dialog badge", async () => {
343
+ await pillNamed("Enterprise Edition, User limit exceeded");
415
344
 
416
- expect(
417
- await screen.findByText("Every licensed seat is in use"),
418
- ).toBeInTheDocument();
419
- expect(screen.getByText("Limit exceeded")).toBeInTheDocument();
345
+ fireEvent.click(screen.getByRole("button", { name: /Enterprise Edition/ }));
346
+
347
+ expect(await screen.findByText("Seat limit exceeded")).toBeInTheDocument();
420
348
  });
421
349
 
422
- it("says plainly that no more users can be added", async () => {
423
- await openDialog();
350
+ it("measures against the live enforced usage rather than the last reported count", async () => {
351
+ respond = (): HTTPResponse<JSONObject> => {
352
+ return new HTTPResponse<JSONObject>(
353
+ 200,
354
+ licensePayload({ currentUserCount: 40, seatsInUse: 50 }),
355
+ {},
356
+ );
357
+ };
424
358
 
425
- expect(
426
- await screen.findByText(
427
- /New users cannot be invited, signed up or provisioned/,
428
- ),
429
- ).toBeInTheDocument();
359
+ await pillNamed("Enterprise Edition, User limit exceeded");
430
360
  });
431
361
 
432
- /*
433
- * seatsInUse is computed from the live User table; currentUserCount is the
434
- * licence-wide figure oneuptime.com last computed, up to a day ago. The card
435
- * has to show the one enforcement uses, or it contradicts the invitation that
436
- * just bounced.
437
- */
438
- it("shows the live enforced usage rather than the last reported count", async () => {
362
+ it("says nothing is wrong when the server reports no enforcement and seats are free", async () => {
439
363
  respond = (): HTTPResponse<JSONObject> => {
440
364
  return new HTTPResponse<JSONObject>(
441
365
  200,
442
366
  licensePayload({
443
- currentUserCount: 40,
444
- seatsInUse: 50,
367
+ isSeatLimitEnforced: false,
368
+ seatsInUse: null,
369
+ seatsRemaining: null,
370
+ canAddMoreUsers: true,
371
+ currentUserCount: 10,
372
+ userLimit: 50,
445
373
  }),
446
374
  {},
447
375
  );
448
376
  };
449
377
 
450
- await openDialog();
451
-
452
- await waitFor(() => {
453
- expect(screen.getByText("Licensed seats")).toBeInTheDocument();
454
- });
455
-
456
- expect(screen.getByText("50")).toBeInTheDocument();
457
- expect(screen.queryByText("40")).not.toBeInTheDocument();
378
+ await pillNamed("Enterprise Edition, View details");
458
379
  });
459
380
 
460
- /*
461
- * A build or a deployment that reports no enforcement must not be rendered as
462
- * one that is refusing users.
463
- */
464
- it("says nothing about enforcement when the server reports none", async () => {
381
+ it("nudges when seats are nearly full", async () => {
465
382
  respond = (): HTTPResponse<JSONObject> => {
466
383
  return new HTTPResponse<JSONObject>(
467
384
  200,
@@ -470,24 +387,13 @@ describe("EditionLabel - what an exhausted seat limit looks like", () => {
470
387
  seatsInUse: null,
471
388
  seatsRemaining: null,
472
389
  canAddMoreUsers: true,
473
- currentUserCount: 10,
390
+ currentUserCount: 46,
474
391
  userLimit: 50,
475
392
  }),
476
393
  {},
477
394
  );
478
395
  };
479
396
 
480
- await openDialog();
481
-
482
- await waitFor(() => {
483
- expect(screen.getByText("Licensed seats")).toBeInTheDocument();
484
- });
485
-
486
- expect(
487
- screen.queryByText(/New users cannot be invited/),
488
- ).not.toBeInTheDocument();
489
- expect(
490
- screen.queryByText(/This installation enforces the seat limit/),
491
- ).not.toBeInTheDocument();
397
+ await pillNamed("Enterprise Edition, Seats nearly full");
492
398
  });
493
399
  });