@oneuptime/common 12.0.6 → 12.0.7

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 (424) hide show
  1. package/Models/DatabaseModels/AIInsight.ts +1 -1
  2. package/Models/DatabaseModels/DatabaseBaseModel/FileModel.ts +2 -3
  3. package/Models/DatabaseModels/DeletedProject.ts +595 -0
  4. package/Models/DatabaseModels/Index.ts +2 -0
  5. package/Models/DatabaseModels/Monitor.ts +111 -0
  6. package/Models/DatabaseModels/Project.ts +3 -3
  7. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -1
  8. package/Server/API/FileAPI.ts +15 -2
  9. package/Server/API/MicrosoftTeamsAPI.ts +6 -1
  10. package/Server/API/ProjectAPI.ts +214 -0
  11. package/Server/API/StatusPageAPI.ts +39 -6
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.ts +50 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.ts +67 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.ts +39 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  16. package/Server/Services/AIAgentService.ts +20 -0
  17. package/Server/Services/DashboardDomainService.ts +73 -28
  18. package/Server/Services/DatabaseService.ts +1 -0
  19. package/Server/Services/DeletedProjectService.ts +138 -0
  20. package/Server/Services/FileService.ts +61 -0
  21. package/Server/Services/IncidentEpisodePublicNoteService.ts +18 -0
  22. package/Server/Services/IncidentPublicNoteService.ts +18 -0
  23. package/Server/Services/Index.ts +2 -0
  24. package/Server/Services/MonitorService.ts +311 -0
  25. package/Server/Services/ProbeService.ts +20 -0
  26. package/Server/Services/ProjectService.ts +297 -1
  27. package/Server/Services/PushNotificationService.ts +71 -0
  28. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +18 -0
  29. package/Server/Services/StatusPageAnnouncementService.ts +53 -0
  30. package/Server/Services/StatusPageDomainService.ts +73 -28
  31. package/Server/Services/TeamMemberService.ts +117 -12
  32. package/Server/Services/TelemetryIngestionKeyService.ts +1 -0
  33. package/Server/Services/UserWebhookService.ts +34 -109
  34. package/Server/Services/WorkspaceNotificationRuleService.ts +69 -0
  35. package/Server/Services/WorkspaceProjectAuthTokenService.ts +37 -1
  36. package/Server/Types/Database/DeleteById.ts +2 -0
  37. package/Server/Types/Database/DeleteOneBy.ts +6 -0
  38. package/Server/Types/Domain.ts +41 -0
  39. package/Server/Types/Workflow/Components/API/Delete.ts +2 -1
  40. package/Server/Types/Workflow/Components/API/Get.ts +2 -1
  41. package/Server/Types/Workflow/Components/API/Patch.ts +2 -1
  42. package/Server/Types/Workflow/Components/API/Post.ts +2 -1
  43. package/Server/Types/Workflow/Components/API/Put.ts +2 -1
  44. package/Server/Types/Workflow/Components/API/Utils.ts +41 -2
  45. package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +25 -19
  46. package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +6 -5
  47. package/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.ts +32 -14
  48. package/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts +31 -13
  49. package/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts +29 -20
  50. package/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts +28 -21
  51. package/Server/Types/Workflow/Components/BaseModel/LogComponentError.ts +89 -0
  52. package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +208 -0
  53. package/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts +11 -0
  54. package/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts +41 -18
  55. package/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts +45 -19
  56. package/Server/Types/Workflow/Components/Discord/SendMessageToChannel.ts +16 -9
  57. package/Server/Types/Workflow/Components/IncomingWebhookUtils.ts +66 -0
  58. package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +15 -9
  59. package/Server/Types/Workflow/Components/Slack/SendMessageToChannel.ts +17 -0
  60. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
  61. package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +171 -0
  62. package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +3 -3
  63. package/Server/Utils/AI/SRE/Insights/FixRouting.ts +3 -2
  64. package/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.ts +1 -1
  65. package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +6 -6
  66. package/Server/Utils/CodeRepository/GitHub/GitHub.ts +43 -5
  67. package/Server/Utils/DataSource/EgressGuard.ts +176 -16
  68. package/Server/Utils/DataSource/HttpFetch.ts +6 -45
  69. package/Server/Utils/Execute.ts +8 -0
  70. package/Server/Utils/InlineImageAccessTokenSync.ts +23 -0
  71. package/Server/Utils/LLM/LLMService.ts +57 -12
  72. package/Server/Utils/Monitor/MonitorAlert.ts +40 -0
  73. package/Server/Utils/Monitor/MonitorDependencySuppression.ts +192 -0
  74. package/Server/Utils/Monitor/MonitorIncident.ts +40 -0
  75. package/Server/Utils/Monitor/MonitorResource.ts +36 -0
  76. package/Server/Utils/Response.ts +142 -6
  77. package/Server/Utils/SSRFProtection.ts +273 -60
  78. package/Server/Utils/StartServer.ts +8 -0
  79. package/Server/Utils/VM/VMRunner.ts +88 -1
  80. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +555 -49
  81. package/Server/Utils/Workspace/Slack/Slack.ts +25 -2
  82. package/Server/Utils/Workspace/WorkspaceBase.ts +6 -0
  83. package/Tests/App/Dashboard/DangerZone.test.tsx +334 -0
  84. package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +539 -0
  85. package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +678 -0
  86. package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +706 -0
  87. package/Tests/App/Dashboard/DashboardVariablesModal.test.tsx +508 -0
  88. package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +470 -0
  89. package/Tests/App/StatusPage/StatusPageDetailPagesNotFound.test.tsx +308 -0
  90. package/Tests/Models/DatabaseModels/DeletedProjectModel.test.ts +251 -0
  91. package/Tests/Models/DatabaseModels/SavedViewJSONColumnTuples.test.ts +115 -0
  92. package/Tests/Server/API/FileAPIAccessControl.test.ts +316 -0
  93. package/Tests/Server/API/ProjectAPI.test.ts +299 -1
  94. package/Tests/Server/API/ProjectAPIAdjustBalance.test.ts +459 -0
  95. package/Tests/Server/API/ProjectAPIAdjustBalanceBillingDisabled.test.ts +177 -0
  96. package/Tests/Server/Services/DatabaseServiceDeletionReason.test.ts +123 -0
  97. package/Tests/Server/Services/DeletedProjectService.test.ts +415 -0
  98. package/Tests/Server/Services/DeletedProjectServiceSelfHosted.test.ts +70 -0
  99. package/Tests/Server/Services/DomainSubdomainHooks.test.ts +94 -0
  100. package/Tests/Server/Services/FileIsPublicBooleanMigration.test.ts +244 -0
  101. package/Tests/Server/Services/FileServiceMimeType.test.ts +89 -0
  102. package/Tests/Server/Services/MonitorServiceDependencyValidation.test.ts +702 -0
  103. package/Tests/Server/Services/ProjectServiceAdjustBalance.test.ts +615 -0
  104. package/Tests/Server/Services/ProjectServiceDeleteAudit.test.ts +406 -0
  105. package/Tests/Server/Services/PublishTimeImageVisibility.test.ts +450 -0
  106. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +669 -0
  107. package/Tests/Server/Services/UserWebhookSSRF.test.ts +174 -0
  108. package/Tests/Server/Services/WebPushEndpointAllowlist.test.ts +133 -0
  109. package/Tests/Server/Services/WorkspaceProjectAuthTokenRepoint.test.ts +618 -0
  110. package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +26 -1
  111. package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +215 -0
  112. package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +742 -0
  113. package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +256 -0
  114. package/Tests/Server/Types/Workflow/Components/ModelArguments.test.ts +371 -0
  115. package/Tests/Server/Utils/AI/CodeAgentCommandGuard.test.ts +204 -0
  116. package/Tests/Server/Utils/AI/CodeAgentWriteLimits.test.ts +213 -0
  117. package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +52 -5
  118. package/Tests/Server/Utils/AI/LLMServiceBaseUrl.test.ts +3 -0
  119. package/Tests/Server/Utils/AI/LLMServiceEgressGuard.test.ts +315 -0
  120. package/Tests/Server/Utils/AI/LLMServiceModelCompatibility.test.ts +3 -0
  121. package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +17 -5
  122. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +14 -1
  123. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +35 -0
  124. package/Tests/Server/Utils/AI/StubLLMEgressGuard.ts +25 -0
  125. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +62 -7
  126. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +69 -0
  127. package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +330 -0
  128. package/Tests/Server/Utils/GitHubCreatePullRequestWithToken.test.ts +393 -0
  129. package/Tests/Server/Utils/InlineImageAccessTokenSync.test.ts +202 -0
  130. package/Tests/Server/Utils/Monitor/MonitorDependencySuppression.test.ts +811 -0
  131. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +604 -0
  132. package/Tests/Server/Utils/ResponseSendFileResponse.test.ts +192 -0
  133. package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +406 -0
  134. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +194 -0
  135. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +1169 -0
  136. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +2 -0
  137. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +1605 -0
  138. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTenantResolution.test.ts +1218 -0
  139. package/Tests/Types/AI/AIChatMessageStatus.test.ts +79 -0
  140. package/Tests/Types/AI/AIInsightStatus.test.ts +40 -0
  141. package/Tests/Types/API/HostnameAuthorityParsing.test.ts +157 -0
  142. package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +27 -0
  143. package/Tests/Types/DataSource/DataSourceLimits.test.ts +71 -0
  144. package/Tests/Types/DataSource/DataSourceType.test.ts +181 -0
  145. package/Tests/Types/DomainSubdomainValidation.test.ts +90 -0
  146. package/Tests/Types/JSONFunctions.test.ts +252 -1
  147. package/Tests/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.test.ts +61 -0
  148. package/Tests/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.test.ts +62 -0
  149. package/Tests/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.test.ts +68 -0
  150. package/Tests/Types/Monitor/SnmpMonitor/SnmpVersion.test.ts +51 -0
  151. package/Tests/UI/Components/404.test.tsx +1 -1
  152. package/Tests/UI/Components/Alert.test.tsx +1 -1
  153. package/Tests/UI/Components/Badge.test.tsx +1 -1
  154. package/Tests/UI/Components/BasicForm.test.tsx +39 -10
  155. package/Tests/UI/Components/Button.test.tsx +1 -1
  156. package/Tests/UI/Components/Card.test.tsx +1 -1
  157. package/Tests/UI/Components/Charts/AxisTickColor.test.tsx +1 -1
  158. package/Tests/UI/Components/ColorViewer.test.tsx +1 -1
  159. package/Tests/UI/Components/ComponentsModal.test.tsx +7 -1
  160. package/Tests/UI/Components/DictionaryOfStrings.test.tsx +1 -1
  161. package/Tests/UI/Components/Dropdown.test.tsx +1 -1
  162. package/Tests/UI/Components/FilePicker.test.tsx +1 -1
  163. package/Tests/UI/Components/HiddenText.test.tsx +1 -1
  164. package/Tests/UI/Components/Input.test.tsx +1 -1
  165. package/Tests/UI/Components/Loader.test.tsx +1 -1
  166. package/Tests/UI/Components/LogTimeRangePicker.test.tsx +1 -1
  167. package/Tests/UI/Components/MasterPage.test.tsx +1 -1
  168. package/Tests/UI/Components/ModalPortalDismissal.test.tsx +489 -0
  169. package/Tests/UI/Components/ModelDelete.test.tsx +214 -0
  170. package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1 -1
  171. package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +1 -1
  172. package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +1 -1
  173. package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +1 -1
  174. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1 -1
  175. package/Tests/UI/Components/NavBar.test.tsx +1 -1
  176. package/Tests/UI/Components/OperatorSelectorKeyboard.test.tsx +1 -1
  177. package/Tests/UI/Components/Pagination.test.tsx +1 -1
  178. package/Tests/UI/Components/Pill.test.tsx +1 -1
  179. package/Tests/UI/Components/Probe.test.tsx +1 -1
  180. package/Tests/UI/Components/ProgressBar.test.tsx +1 -1
  181. package/Tests/UI/Components/RadioButtons.test.tsx +1 -1
  182. package/Tests/UI/Components/SideMenuItem.test.tsx +1 -1
  183. package/Tests/UI/Components/SideOver.test.tsx +500 -6
  184. package/Tests/UI/Components/Tabs.test.tsx +1 -1
  185. package/Tests/UI/Components/TelemetrySearchBar.test.tsx +1 -1
  186. package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +1 -1
  187. package/Tests/UI/Components/TextArea.test.tsx +1 -1
  188. package/Tests/UI/Components/Toast.test.tsx +1 -1
  189. package/Tests/UI/Components/Toggle.test.tsx +1 -1
  190. package/Tests/UI/Components/TopSection.test.tsx +1 -1
  191. package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +1 -1
  192. package/Tests/UI/Rum/ReplayScrubber.test.tsx +1 -1
  193. package/Tests/UI/Rum/ReplayStage.test.tsx +1 -1
  194. package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +1 -1
  195. package/Tests/UI/Utils/LocalStorageArrayRoundTrip.test.ts +72 -0
  196. package/Tests/Utils/Dashboard/HtmlWidgetDocument.test.ts +19 -2
  197. package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +44 -0
  198. package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +288 -5
  199. package/Tests/Utils/Dashboard/VariableUrlState.test.ts +42 -0
  200. package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +27 -0
  201. package/Tests/Utils/LegacySerializedArray.test.ts +139 -0
  202. package/Tests/Utils/Monitor/MonitorDependencyRule.test.ts +190 -0
  203. package/Tests/Utils/Realtime.test.ts +78 -0
  204. package/Tests/Utils/Telemetry/SavedViewFilters.test.ts +246 -0
  205. package/Tests/__mocks__/i18next-browser-languagedetector.js +21 -0
  206. package/Types/AI/FixPullRequestCiStatus.ts +1 -1
  207. package/Types/AI/FixVerificationStatus.ts +2 -2
  208. package/Types/API/Hostname.ts +92 -4
  209. package/Types/API/URL.ts +43 -25
  210. package/Types/Billing/BalanceAdjustmentType.ts +14 -0
  211. package/Types/Billing/ProjectBalanceType.ts +13 -0
  212. package/Types/Domain.ts +26 -0
  213. package/Types/File/MimeType.ts +11 -0
  214. package/Types/JSONFunctions.ts +15 -0
  215. package/Types/Telemetry/TelemetrySavedViewState.ts +9 -1
  216. package/Types/Workflow/Components/BaseModel.ts +92 -28
  217. package/Typings/Index.d.ts +12 -0
  218. package/UI/Components/GanttChart/ChartContainer.tsx +4 -3
  219. package/UI/Components/Modal/ConfirmModal.tsx +10 -5
  220. package/UI/Components/Modal/Modal.tsx +27 -47
  221. package/UI/Components/ModelDelete/ModelDelete.tsx +23 -6
  222. package/UI/Components/SideOver/SideOver.tsx +195 -68
  223. package/UI/Utils/PageScrollLock.ts +66 -0
  224. package/Utils/Dashboard/HtmlWidgetDocument.ts +4 -2
  225. package/Utils/Dashboard/VariableInterpolation.ts +19 -1
  226. package/Utils/LegacySerializedArray.ts +60 -0
  227. package/Utils/Monitor/MonitorDependencyRule.ts +88 -0
  228. package/Utils/Telemetry/SavedViewFilters.ts +88 -0
  229. package/build/dist/Models/DatabaseModels/AIInsight.js +1 -1
  230. package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -1
  231. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js +2 -3
  232. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js.map +1 -1
  233. package/build/dist/Models/DatabaseModels/DeletedProject.js +640 -0
  234. package/build/dist/Models/DatabaseModels/DeletedProject.js.map +1 -0
  235. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  236. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  237. package/build/dist/Models/DatabaseModels/Monitor.js +106 -0
  238. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  239. package/build/dist/Models/DatabaseModels/Project.js +3 -3
  240. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  241. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  242. package/build/dist/Server/API/FileAPI.js +14 -2
  243. package/build/dist/Server/API/FileAPI.js.map +1 -1
  244. package/build/dist/Server/API/MicrosoftTeamsAPI.js +6 -1
  245. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  246. package/build/dist/Server/API/ProjectAPI.js +157 -4
  247. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  248. package/build/dist/Server/API/StatusPageAPI.js +27 -3
  249. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  250. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js +34 -0
  251. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js.map +1 -0
  252. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js +30 -0
  253. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js.map +1 -0
  254. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js +20 -0
  255. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js.map +1 -0
  256. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  257. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  258. package/build/dist/Server/Services/AIAgentService.js +17 -0
  259. package/build/dist/Server/Services/AIAgentService.js.map +1 -1
  260. package/build/dist/Server/Services/DashboardDomainService.js +55 -18
  261. package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
  262. package/build/dist/Server/Services/DatabaseService.js +1 -0
  263. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  264. package/build/dist/Server/Services/DeletedProjectService.js +124 -0
  265. package/build/dist/Server/Services/DeletedProjectService.js.map +1 -0
  266. package/build/dist/Server/Services/FileService.js +52 -0
  267. package/build/dist/Server/Services/FileService.js.map +1 -1
  268. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +10 -1
  269. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
  270. package/build/dist/Server/Services/IncidentPublicNoteService.js +10 -1
  271. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  272. package/build/dist/Server/Services/Index.js +2 -0
  273. package/build/dist/Server/Services/Index.js.map +1 -1
  274. package/build/dist/Server/Services/MonitorService.js +232 -0
  275. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  276. package/build/dist/Server/Services/ProbeService.js +17 -0
  277. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  278. package/build/dist/Server/Services/ProjectService.js +228 -6
  279. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  280. package/build/dist/Server/Services/PushNotificationService.js +56 -0
  281. package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
  282. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +10 -1
  283. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  284. package/build/dist/Server/Services/StatusPageAnnouncementService.js +54 -0
  285. package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
  286. package/build/dist/Server/Services/StatusPageDomainService.js +55 -18
  287. package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
  288. package/build/dist/Server/Services/TeamMemberService.js +97 -6
  289. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  290. package/build/dist/Server/Services/TelemetryIngestionKeyService.js +1 -0
  291. package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
  292. package/build/dist/Server/Services/UserWebhookService.js +31 -87
  293. package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
  294. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +65 -0
  295. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  296. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +23 -0
  297. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
  298. package/build/dist/Server/Types/Domain.js +37 -0
  299. package/build/dist/Server/Types/Domain.js.map +1 -1
  300. package/build/dist/Server/Types/Workflow/Components/API/Delete.js +2 -1
  301. package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
  302. package/build/dist/Server/Types/Workflow/Components/API/Get.js +2 -1
  303. package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
  304. package/build/dist/Server/Types/Workflow/Components/API/Patch.js +2 -1
  305. package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
  306. package/build/dist/Server/Types/Workflow/Components/API/Post.js +2 -1
  307. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  308. package/build/dist/Server/Types/Workflow/Components/API/Put.js +2 -1
  309. package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
  310. package/build/dist/Server/Types/Workflow/Components/API/Utils.js +35 -2
  311. package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
  312. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +15 -11
  313. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
  314. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +2 -3
  315. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
  316. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js +21 -10
  317. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js.map +1 -1
  318. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js +21 -10
  319. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js.map +1 -1
  320. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js +18 -13
  321. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js.map +1 -1
  322. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js +18 -13
  323. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js.map +1 -1
  324. package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js +43 -0
  325. package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js.map +1 -0
  326. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +116 -0
  327. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -0
  328. package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js +7 -0
  329. package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js.map +1 -1
  330. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js +24 -13
  331. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js.map +1 -1
  332. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js +27 -13
  333. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js.map +1 -1
  334. package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js +14 -6
  335. package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js.map +1 -1
  336. package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js +42 -0
  337. package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js.map +1 -0
  338. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +15 -6
  339. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
  340. package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js +10 -2
  341. package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js.map +1 -1
  342. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
  343. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +141 -0
  344. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -1
  345. package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -1
  346. package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js +1 -1
  347. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +6 -6
  348. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js.map +1 -1
  349. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +39 -5
  350. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
  351. package/build/dist/Server/Utils/DataSource/EgressGuard.js +94 -10
  352. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
  353. package/build/dist/Server/Utils/DataSource/HttpFetch.js +1 -19
  354. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  355. package/build/dist/Server/Utils/Execute.js +2 -2
  356. package/build/dist/Server/Utils/Execute.js.map +1 -1
  357. package/build/dist/Server/Utils/InlineImageAccessTokenSync.js +13 -0
  358. package/build/dist/Server/Utils/InlineImageAccessTokenSync.js.map +1 -1
  359. package/build/dist/Server/Utils/LLM/LLMService.js +43 -12
  360. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  361. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +44 -24
  362. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  363. package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js +158 -0
  364. package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js.map +1 -0
  365. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +50 -30
  366. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  367. package/build/dist/Server/Utils/Monitor/MonitorResource.js +32 -0
  368. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  369. package/build/dist/Server/Utils/Response.js +112 -5
  370. package/build/dist/Server/Utils/Response.js.map +1 -1
  371. package/build/dist/Server/Utils/SSRFProtection.js +219 -53
  372. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  373. package/build/dist/Server/Utils/StartServer.js +7 -0
  374. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  375. package/build/dist/Server/Utils/VM/VMRunner.js +73 -1
  376. package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
  377. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +445 -43
  378. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  379. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +18 -1
  380. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  381. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  382. package/build/dist/Types/AI/FixPullRequestCiStatus.js +1 -1
  383. package/build/dist/Types/AI/FixVerificationStatus.js +2 -2
  384. package/build/dist/Types/API/Hostname.js +73 -4
  385. package/build/dist/Types/API/Hostname.js.map +1 -1
  386. package/build/dist/Types/API/URL.js +42 -24
  387. package/build/dist/Types/API/URL.js.map +1 -1
  388. package/build/dist/Types/Billing/BalanceAdjustmentType.js +15 -0
  389. package/build/dist/Types/Billing/BalanceAdjustmentType.js.map +1 -0
  390. package/build/dist/Types/Billing/ProjectBalanceType.js +14 -0
  391. package/build/dist/Types/Billing/ProjectBalanceType.js.map +1 -0
  392. package/build/dist/Types/Domain.js +22 -0
  393. package/build/dist/Types/Domain.js.map +1 -1
  394. package/build/dist/Types/File/MimeType.js +11 -0
  395. package/build/dist/Types/File/MimeType.js.map +1 -1
  396. package/build/dist/Types/JSONFunctions.js +14 -0
  397. package/build/dist/Types/JSONFunctions.js.map +1 -1
  398. package/build/dist/Types/Workflow/Components/BaseModel.js +83 -28
  399. package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
  400. package/build/dist/UI/Components/GanttChart/ChartContainer.js +4 -3
  401. package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +1 -1
  402. package/build/dist/UI/Components/Modal/ConfirmModal.js +3 -1
  403. package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
  404. package/build/dist/UI/Components/Modal/Modal.js +24 -34
  405. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  406. package/build/dist/UI/Components/ModelDelete/ModelDelete.js +11 -6
  407. package/build/dist/UI/Components/ModelDelete/ModelDelete.js.map +1 -1
  408. package/build/dist/UI/Components/SideOver/SideOver.js +105 -30
  409. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  410. package/build/dist/UI/Utils/PageScrollLock.js +52 -0
  411. package/build/dist/UI/Utils/PageScrollLock.js.map +1 -0
  412. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js +4 -2
  413. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js.map +1 -1
  414. package/build/dist/Utils/Dashboard/VariableInterpolation.js +19 -1
  415. package/build/dist/Utils/Dashboard/VariableInterpolation.js.map +1 -1
  416. package/build/dist/Utils/LegacySerializedArray.js +51 -0
  417. package/build/dist/Utils/LegacySerializedArray.js.map +1 -0
  418. package/build/dist/Utils/Monitor/MonitorDependencyRule.js +47 -0
  419. package/build/dist/Utils/Monitor/MonitorDependencyRule.js.map +1 -0
  420. package/build/dist/Utils/Telemetry/SavedViewFilters.js +52 -0
  421. package/build/dist/Utils/Telemetry/SavedViewFilters.js.map +1 -0
  422. package/jest.config.json +3 -0
  423. package/package.json +1 -1
  424. package/tsconfig.json +3 -1
@@ -1,10 +1,81 @@
1
+ import Modal from "../../../UI/Components/Modal/Modal";
1
2
  import SideOver, {
2
3
  ComponentProps,
4
+ SideOverSize,
3
5
  } from "../../../UI/Components/SideOver/SideOver";
4
- import "@testing-library/jest-dom/extend-expect";
5
- import { fireEvent, render, screen } from "@testing-library/react";
6
+ /*
7
+ * The main entry, not "/extend-expect": the latter no longer ships type
8
+ * declarations, so every jest-dom matcher in this file fails to typecheck and
9
+ * the whole suite is skipped before a single assertion runs.
10
+ */
11
+ import "@testing-library/jest-dom";
12
+ import { resetPageScrollLockForTesting } from "../../../UI/Utils/PageScrollLock";
13
+ import {
14
+ fireEvent,
15
+ render,
16
+ RenderResult,
17
+ screen,
18
+ } from "@testing-library/react";
6
19
  import React, { ReactElement } from "react";
7
- import { describe, expect, test, afterEach, jest } from "@jest/globals";
20
+ import {
21
+ afterEach,
22
+ beforeEach,
23
+ describe,
24
+ expect,
25
+ jest,
26
+ test,
27
+ } from "@jest/globals";
28
+
29
+ /*
30
+ * SideOver is the app's right-hand drawer. Most of what is pinned below comes
31
+ * straight out of issue #3134: the panel used to sit at z-10 inside whatever
32
+ * container rendered it, so a network map's zoom toolbar (z-20) painted on top
33
+ * of an open device panel, and the page kept its own scrollbar live down the
34
+ * panel's right edge. The layering is now structural — a portal out of the
35
+ * caller's DOM plus one deliberate z-index — so it is worth asserting the
36
+ * structure rather than just the classes.
37
+ */
38
+
39
+ /*
40
+ * The de-facto layering ladder of this app, pinned here because nothing else
41
+ * writes it down in one place. SideOver has to clear every tier of page chrome
42
+ * and stay under every app-wide overlay; both halves are load-bearing.
43
+ */
44
+ const SIDE_OVER_Z_INDEX: number = 30;
45
+ const PAGE_CHROME_Z_INDEXES: Array<number> = [
46
+ 10 /* MasterPage sticky header */, 20 /* topology + logs viewer toolbars */,
47
+ ];
48
+ const OVERLAY_Z_INDEXES_ABOVE_SIDE_OVER: Array<number> = [
49
+ 40 /* Toast, AIChatPanel */, 50 /* Modal */, 60 /* portalled dropdowns */,
50
+ ];
51
+
52
+ type ZIndexOfFunction = (element: HTMLElement) => number | null;
53
+
54
+ const zIndexOf: ZIndexOfFunction = (element: HTMLElement): number | null => {
55
+ const match: RegExpMatchArray | null = element.className.match(
56
+ /(?:^|\s)z-(\d+)(?:\s|$)/,
57
+ );
58
+
59
+ return match && match[1] !== undefined ? Number(match[1]) : null;
60
+ };
61
+
62
+ type SetFullscreenElementFunction = (element: Element | null) => void;
63
+
64
+ /*
65
+ * jsdom implements no Fullscreen API at all, so both the property and the
66
+ * event it is announced with have to be faked. The panel follows
67
+ * document.fullscreenElement because only the fullscreen element's own subtree
68
+ * reaches the browser's top layer.
69
+ */
70
+ const setFullscreenElement: SetFullscreenElementFunction = (
71
+ element: Element | null,
72
+ ): void => {
73
+ Object.defineProperty(document, "fullscreenElement", {
74
+ configurable: true,
75
+ value: element,
76
+ });
77
+ fireEvent(document, new Event("fullscreenchange"));
78
+ };
8
79
 
9
80
  describe("SideOver", () => {
10
81
  const childElementText: string = "child element";
@@ -18,18 +89,34 @@ describe("SideOver", () => {
18
89
  children: childElement,
19
90
  };
20
91
 
21
- type RenderComponentFunction = (props: ComponentProps) => void;
92
+ type RenderComponentFunction = (props: ComponentProps) => RenderResult;
22
93
 
23
94
  const renderComponent: RenderComponentFunction = (
24
95
  props: ComponentProps,
25
- ): void => {
26
- render(<SideOver {...props} />);
96
+ ): RenderResult => {
97
+ return render(<SideOver {...props} />);
27
98
  };
28
99
 
100
+ beforeEach(() => {
101
+ resetPageScrollLockForTesting();
102
+ document.body.style.overflow = "";
103
+ document.body.style.paddingRight = "";
104
+ });
105
+
29
106
  afterEach(() => {
30
107
  jest.clearAllMocks();
108
+ setFullscreenElement(null);
109
+ resetPageScrollLockForTesting();
110
+ document.body.style.overflow = "";
111
+ document.body.style.paddingRight = "";
31
112
  });
32
113
 
114
+ /*
115
+ * ------------------------------------------------------------------
116
+ * Existing contract
117
+ * ------------------------------------------------------------------
118
+ */
119
+
33
120
  test("should display title", () => {
34
121
  renderComponent(props);
35
122
 
@@ -109,4 +196,411 @@ describe("SideOver", () => {
109
196
  fireEvent.click(saveButton);
110
197
  expect(props.onSubmit).toHaveBeenCalled();
111
198
  });
199
+
200
+ /*
201
+ * ------------------------------------------------------------------
202
+ * Layering — issue #3134
203
+ * ------------------------------------------------------------------
204
+ */
205
+
206
+ describe("layering", () => {
207
+ test("puts the panel above page chrome and below every app-wide overlay", () => {
208
+ renderComponent(props);
209
+
210
+ const root: HTMLElement = screen.getByTestId("side-over");
211
+
212
+ expect(zIndexOf(root)).toBe(SIDE_OVER_Z_INDEX);
213
+
214
+ for (const chrome of PAGE_CHROME_Z_INDEXES) {
215
+ expect(SIDE_OVER_Z_INDEX).toBeGreaterThan(chrome);
216
+ }
217
+
218
+ for (const overlay of OVERLAY_Z_INDEXES_ABOVE_SIDE_OVER) {
219
+ expect(SIDE_OVER_Z_INDEX).toBeLessThan(overlay);
220
+ }
221
+ });
222
+
223
+ test("no longer sits at z-10, which lost to the map toolbar's z-20", () => {
224
+ renderComponent(props);
225
+
226
+ expect(screen.getByTestId("side-over")).not.toHaveClass("z-10");
227
+ });
228
+
229
+ test("portals out of the caller's DOM so no ancestor can trap it in a stacking context", () => {
230
+ const { container }: RenderResult = renderComponent(props);
231
+
232
+ const root: HTMLElement = screen.getByTestId("side-over");
233
+
234
+ expect(container).not.toContainElement(root);
235
+ expect(root.parentElement).toBe(document.body);
236
+ });
237
+
238
+ test("escapes a z-indexed ancestor, which is how the map toolbar ended up on top of it", () => {
239
+ /*
240
+ * The reported reproduction, in miniature: the panel is rendered as a
241
+ * sibling of a toolbar inside a card, and the toolbar outranks it. While
242
+ * the panel stayed inside that subtree no z-index on it could win,
243
+ * because the whole subtree resolved against the same ancestor.
244
+ */
245
+ render(
246
+ <div className="relative" data-testid="map-card">
247
+ <div
248
+ className="absolute right-2 top-2 z-20"
249
+ data-testid="map-toolbar"
250
+ >
251
+ zoom controls
252
+ </div>
253
+ <SideOver {...props} />
254
+ </div>,
255
+ );
256
+
257
+ const card: HTMLElement = screen.getByTestId("map-card");
258
+ const root: HTMLElement = screen.getByTestId("side-over");
259
+
260
+ expect(card).toContainElement(screen.getByTestId("map-toolbar"));
261
+ expect(card).not.toContainElement(root);
262
+ expect(root.parentElement).toBe(document.body);
263
+ });
264
+
265
+ test("leaves nothing between the fixed layer and the document body except the one z-indexed root", () => {
266
+ renderComponent(props);
267
+
268
+ const root: HTMLElement = screen.getByTestId("side-over");
269
+ const layer: HTMLElement = screen.getByTestId("side-over-layer");
270
+
271
+ expect(layer.parentElement).toBe(root);
272
+
273
+ /*
274
+ * Every ancestor above the root must be free of anything that would
275
+ * create a stacking context, or the root's z-30 would be resolved
276
+ * against that ancestor instead of against the page. This is the actual
277
+ * shape of the #3134 bug, so walk it rather than trusting the classes.
278
+ */
279
+ let ancestor: HTMLElement | null = root.parentElement;
280
+
281
+ while (ancestor && ancestor !== document.documentElement) {
282
+ expect(zIndexOf(ancestor)).toBeNull();
283
+ expect(ancestor.className).not.toMatch(
284
+ /(^|\s)(transform|opacity-\d+|filter|isolate|backdrop-blur)(\s|$)/,
285
+ );
286
+ ancestor = ancestor.parentElement;
287
+ }
288
+ });
289
+
290
+ test("renders the panel layer over the whole viewport but only takes pointer events on the panel itself", () => {
291
+ renderComponent(props);
292
+
293
+ const layer: HTMLElement = screen.getByTestId("side-over-layer");
294
+
295
+ expect(layer).toHaveClass("fixed", "inset-0", "pointer-events-none");
296
+ expect(layer).toHaveClass("justify-end");
297
+ expect(layer.firstElementChild).toHaveClass("pointer-events-auto");
298
+ });
299
+
300
+ test("keeps a single element in the root — the vestigial backdrop divs are gone", () => {
301
+ renderComponent(props);
302
+
303
+ const root: HTMLElement = screen.getByTestId("side-over");
304
+
305
+ expect(root.children).toHaveLength(1);
306
+ expect(root.firstElementChild).toBe(
307
+ screen.getByTestId("side-over-layer"),
308
+ );
309
+ });
310
+
311
+ test("follows the fullscreen element, because only its subtree reaches the top layer", () => {
312
+ const fullscreenHost: HTMLDivElement = document.createElement("div");
313
+ document.body.appendChild(fullscreenHost);
314
+
315
+ renderComponent(props);
316
+
317
+ expect(screen.getByTestId("side-over").parentElement).toBe(document.body);
318
+
319
+ setFullscreenElement(fullscreenHost);
320
+
321
+ expect(screen.getByTestId("side-over").parentElement).toBe(
322
+ fullscreenHost,
323
+ );
324
+
325
+ setFullscreenElement(null);
326
+
327
+ expect(screen.getByTestId("side-over").parentElement).toBe(document.body);
328
+
329
+ document.body.removeChild(fullscreenHost);
330
+ });
331
+
332
+ test("mounts straight into the fullscreen element when one is already open", () => {
333
+ const fullscreenHost: HTMLDivElement = document.createElement("div");
334
+ document.body.appendChild(fullscreenHost);
335
+ setFullscreenElement(fullscreenHost);
336
+
337
+ renderComponent(props);
338
+
339
+ expect(screen.getByTestId("side-over").parentElement).toBe(
340
+ fullscreenHost,
341
+ );
342
+
343
+ setFullscreenElement(null);
344
+ document.body.removeChild(fullscreenHost);
345
+ });
346
+ });
347
+
348
+ /*
349
+ * ------------------------------------------------------------------
350
+ * Scrollbars — the other half of issue #3134
351
+ * ------------------------------------------------------------------
352
+ */
353
+
354
+ describe("scrolling", () => {
355
+ test("scrolls the body on demand instead of painting a permanent dead track", () => {
356
+ renderComponent(props);
357
+
358
+ const content: HTMLElement = screen.getByTestId("side-over-content");
359
+
360
+ expect(content).toHaveClass("overflow-y-auto");
361
+ expect(content).not.toHaveClass("overflow-y-scroll");
362
+ });
363
+
364
+ test("contains overscroll so wheeling past the end does not scroll the page underneath", () => {
365
+ renderComponent(props);
366
+
367
+ expect(screen.getByTestId("side-over-content")).toHaveClass(
368
+ "overscroll-contain",
369
+ );
370
+ });
371
+
372
+ test("sizes the panel against its container rather than 100vw, which includes the scrollbar", () => {
373
+ renderComponent(props);
374
+
375
+ const panel: HTMLElement | null = screen.getByTestId("side-over-layer")
376
+ .firstElementChild as HTMLElement;
377
+
378
+ expect(panel).toHaveClass("w-full");
379
+ expect(panel).not.toHaveClass("w-screen");
380
+ });
381
+
382
+ test("hides the page scrollbar while open and puts it back on close", () => {
383
+ document.body.style.overflow = "auto";
384
+
385
+ const rendered: RenderResult = renderComponent(props);
386
+
387
+ expect(document.body.style.overflow).toBe("hidden");
388
+
389
+ rendered.unmount();
390
+
391
+ expect(document.body.style.overflow).toBe("auto");
392
+ });
393
+
394
+ test("leaves the page alone when the scroll lock is disabled", () => {
395
+ document.body.style.overflow = "auto";
396
+
397
+ const rendered: RenderResult = renderComponent({
398
+ ...props,
399
+ disablePageScrollLock: true,
400
+ });
401
+
402
+ expect(document.body.style.overflow).toBe("auto");
403
+
404
+ rendered.unmount();
405
+
406
+ expect(document.body.style.overflow).toBe("auto");
407
+ });
408
+
409
+ test("shares one lock with Modal, so a modal closing inside a panel does not unlock the page", () => {
410
+ document.body.style.overflow = "auto";
411
+
412
+ const rendered: RenderResult = render(
413
+ <SideOver {...props}>
414
+ <div key={0}>
415
+ <Modal title="Nested" onClose={jest.fn()}>
416
+ <div>Nested modal content</div>
417
+ </Modal>
418
+ </div>
419
+ </SideOver>,
420
+ );
421
+
422
+ expect(document.body.style.overflow).toBe("hidden");
423
+
424
+ /*
425
+ * Re-render without the modal: the panel is still open, so the page must
426
+ * stay locked. Two private counters would restore "auto" here.
427
+ */
428
+ rendered.rerender(
429
+ <SideOver {...props}>
430
+ <div key={0} />
431
+ </SideOver>,
432
+ );
433
+
434
+ expect(document.body.style.overflow).toBe("hidden");
435
+
436
+ rendered.unmount();
437
+
438
+ expect(document.body.style.overflow).toBe("auto");
439
+ });
440
+
441
+ test("keeps the page locked while a modal outlives the panel that opened it", () => {
442
+ document.body.style.overflow = "auto";
443
+
444
+ const panel: RenderResult = renderComponent(props);
445
+ const modal: RenderResult = render(
446
+ <Modal title="Standalone" onClose={jest.fn()}>
447
+ <div>Standalone modal content</div>
448
+ </Modal>,
449
+ );
450
+
451
+ expect(document.body.style.overflow).toBe("hidden");
452
+
453
+ panel.unmount();
454
+
455
+ expect(document.body.style.overflow).toBe("hidden");
456
+
457
+ modal.unmount();
458
+
459
+ expect(document.body.style.overflow).toBe("auto");
460
+ });
461
+
462
+ test("restores the page exactly once when two panels are open together", () => {
463
+ document.body.style.overflow = "auto";
464
+
465
+ const first: RenderResult = renderComponent(props);
466
+ const second: RenderResult = renderComponent(props);
467
+
468
+ expect(document.body.style.overflow).toBe("hidden");
469
+
470
+ first.unmount();
471
+
472
+ expect(document.body.style.overflow).toBe("hidden");
473
+
474
+ second.unmount();
475
+
476
+ expect(document.body.style.overflow).toBe("auto");
477
+ });
478
+ });
479
+
480
+ /*
481
+ * ------------------------------------------------------------------
482
+ * Dialog semantics
483
+ * ------------------------------------------------------------------
484
+ */
485
+
486
+ describe("dialog semantics", () => {
487
+ test("does not claim to be modal, because the page behind it stays interactive", () => {
488
+ renderComponent(props);
489
+
490
+ const root: HTMLElement = screen.getByTestId("side-over");
491
+
492
+ expect(root).toHaveAttribute("role", "dialog");
493
+ expect(root).not.toHaveAttribute("aria-modal");
494
+ });
495
+
496
+ test("stays out of Modal's dialog stack so an open modal keeps its Escape key", () => {
497
+ const onModalClose: () => void = jest.fn();
498
+
499
+ /*
500
+ * The modal is rendered FIRST and the panel portals to the end of
501
+ * <body>, so with aria-modal="true" the panel would be the last dialog
502
+ * in tree order and Modal would decide it was no longer topmost.
503
+ */
504
+ render(
505
+ <Modal title="Settings" onClose={onModalClose}>
506
+ <div>Modal content</div>
507
+ </Modal>,
508
+ );
509
+ renderComponent(props);
510
+
511
+ fireEvent.keyDown(document, { key: "Escape" });
512
+
513
+ expect(onModalClose).toHaveBeenCalled();
514
+ });
515
+
516
+ test("labels itself with the title it actually rendered", () => {
517
+ renderComponent(props);
518
+
519
+ const root: HTMLElement = screen.getByTestId("side-over");
520
+ const title: HTMLElement = screen.getByTestId("side-over-title");
521
+
522
+ expect(title.id).toBeTruthy();
523
+ expect(root).toHaveAttribute("aria-labelledby", title.id);
524
+ });
525
+
526
+ test("no longer uses a hardcoded id, so two panels do not announce the same title", () => {
527
+ renderComponent(props);
528
+ renderComponent({ ...props, title: "second title" });
529
+
530
+ const [firstTitle, secondTitle] = screen.getAllByTestId(
531
+ "side-over-title",
532
+ ) as [HTMLElement, HTMLElement];
533
+
534
+ expect(firstTitle.id).not.toBe("slide-over-title");
535
+ expect(secondTitle.id).not.toBe("slide-over-title");
536
+ expect(firstTitle.id).not.toBe(secondTitle.id);
537
+
538
+ const [firstRoot, secondRoot] = screen.getAllByTestId("side-over") as [
539
+ HTMLElement,
540
+ HTMLElement,
541
+ ];
542
+
543
+ expect(firstRoot).toHaveAttribute("aria-labelledby", firstTitle.id);
544
+ expect(secondRoot).toHaveAttribute("aria-labelledby", secondTitle.id);
545
+ });
546
+
547
+ test("wires the description into the accessible description", () => {
548
+ renderComponent(props);
549
+
550
+ const root: HTMLElement = screen.getByTestId("side-over");
551
+ const description: HTMLElement = screen.getByTestId(
552
+ "side-over-description",
553
+ );
554
+
555
+ expect(root).toHaveAttribute("aria-describedby", description.id);
556
+ });
557
+
558
+ test("names the close button so a shared focus helper can skip it", () => {
559
+ renderComponent(props);
560
+
561
+ const closeButton: HTMLElement = screen.getByTestId("close-button");
562
+
563
+ expect(closeButton).toHaveAttribute("title", "Close panel");
564
+
565
+ fireEvent.click(closeButton);
566
+
567
+ expect(props.onClose).toHaveBeenCalled();
568
+ });
569
+ });
570
+
571
+ /*
572
+ * ------------------------------------------------------------------
573
+ * Sizing
574
+ * ------------------------------------------------------------------
575
+ */
576
+
577
+ describe("size", () => {
578
+ type ExpectWidthClassFunction = (
579
+ size: SideOverSize | undefined,
580
+ widthClass: string,
581
+ ) => void;
582
+
583
+ const expectWidthClass: ExpectWidthClassFunction = (
584
+ size: SideOverSize | undefined,
585
+ widthClass: string,
586
+ ): void => {
587
+ const rendered: RenderResult = renderComponent(
588
+ size === undefined ? props : { ...props, size },
589
+ );
590
+
591
+ const panel: HTMLElement = screen.getByTestId("side-over-layer")
592
+ .firstElementChild as HTMLElement;
593
+
594
+ expect(panel).toHaveClass(widthClass);
595
+
596
+ rendered.unmount();
597
+ };
598
+
599
+ test("maps each size onto the width it has always had", () => {
600
+ expectWidthClass(undefined, "max-w-2xl");
601
+ expectWidthClass(SideOverSize.Small, "max-w-2xl");
602
+ expectWidthClass(SideOverSize.Medium, "max-w-5xl");
603
+ expectWidthClass(SideOverSize.Large, "max-w-7xl");
604
+ });
605
+ });
112
606
  });
@@ -1,6 +1,6 @@
1
1
  import { Tab } from "../../../UI/Components/Tabs/Tab";
2
2
  import Tabs from "../../../UI/Components/Tabs/Tabs";
3
- import "@testing-library/jest-dom/extend-expect";
3
+ import "@testing-library/jest-dom";
4
4
  import { fireEvent, render } from "@testing-library/react";
5
5
  import React from "react";
6
6
  import { describe, expect, test } from "@jest/globals";
@@ -1,5 +1,5 @@
1
1
  import TelemetrySearchBar from "../../../UI/Components/TelemetryViewer/components/TelemetrySearchBar";
2
- import "@testing-library/jest-dom/extend-expect";
2
+ import "@testing-library/jest-dom";
3
3
  import { cleanup, fireEvent, render, screen } from "@testing-library/react";
4
4
  import React from "react";
5
5
  import { afterEach, describe, expect, jest, test } from "@jest/globals";
@@ -4,7 +4,7 @@ import TelemetryTimeRangePicker, {
4
4
  import RangeStartAndEndDateTime from "../../../Types/Time/RangeStartAndEndDateTime";
5
5
  import TimeRange from "../../../Types/Time/TimeRange";
6
6
  import InBetween from "../../../Types/BaseDatabase/InBetween";
7
- import "@testing-library/jest-dom/extend-expect";
7
+ import "@testing-library/jest-dom";
8
8
  import {
9
9
  act,
10
10
  cleanup,
@@ -1,5 +1,5 @@
1
1
  import TextArea from "../../../UI/Components/TextArea/TextArea";
2
- import "@testing-library/jest-dom/extend-expect";
2
+ import "@testing-library/jest-dom";
3
3
  import { fireEvent, render } from "@testing-library/react";
4
4
  import React from "react";
5
5
  import { describe, expect, test } from "@jest/globals";
@@ -1,5 +1,5 @@
1
1
  import Toast, { ToastType } from "../../../UI/Components/Toast/Toast";
2
- import "@testing-library/jest-dom/extend-expect";
2
+ import "@testing-library/jest-dom";
3
3
  import { render, screen } from "@testing-library/react";
4
4
  import userEvent from "@testing-library/user-event";
5
5
  import { UserEvent } from "@testing-library/user-event/dist/types/setup/setup";
@@ -1,5 +1,5 @@
1
1
  import Toggle from "../../../UI/Components/Toggle/Toggle";
2
- import "@testing-library/jest-dom/extend-expect";
2
+ import "@testing-library/jest-dom";
3
3
  import { fireEvent, render } from "@testing-library/react";
4
4
  import React from "react";
5
5
  import { describe, expect, test } from "@jest/globals";
@@ -2,7 +2,7 @@ import TopSection, {
2
2
  ComponentProps,
3
3
  } from "../../../UI/Components/TopSection/TopSection";
4
4
  import { describe, expect, it } from "@jest/globals";
5
- import "@testing-library/jest-dom/extend-expect";
5
+ import "@testing-library/jest-dom";
6
6
  import { render, screen } from "@testing-library/react";
7
7
  import React from "react";
8
8
 
@@ -1,5 +1,5 @@
1
1
  import useLiveLogsRefresh from "../../../UI/Components/LogsViewer/useLiveLogsRefresh";
2
- import "@testing-library/jest-dom/extend-expect";
2
+ import "@testing-library/jest-dom";
3
3
  import { act, render } from "@testing-library/react";
4
4
  import React, { FunctionComponent, ReactElement } from "react";
5
5
  import { afterEach, beforeEach, describe, expect, test } from "@jest/globals";
@@ -1,4 +1,4 @@
1
- import "@testing-library/jest-dom/extend-expect";
1
+ import "@testing-library/jest-dom";
2
2
  import { fireEvent, render, screen } from "@testing-library/react";
3
3
  import * as React from "react";
4
4
  import { describe, expect, it } from "@jest/globals";
@@ -1,4 +1,4 @@
1
- import "@testing-library/jest-dom/extend-expect";
1
+ import "@testing-library/jest-dom";
2
2
  import { act, render } from "@testing-library/react";
3
3
  /*
4
4
  * The Dashboard has its own copy of react, so a component imported from there
@@ -1,4 +1,4 @@
1
- import "@testing-library/jest-dom/extend-expect";
1
+ import "@testing-library/jest-dom";
2
2
  import { render, RenderResult } from "@testing-library/react";
3
3
  /*
4
4
  * The Dashboard has its own copy of react, so a component imported from there