@oneuptime/common 12.0.34 → 13.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 (259) hide show
  1. package/Models/DatabaseModels/GlobalConfig.ts +12 -12
  2. package/Models/DatabaseModels/InventoryItem.ts +44 -1
  3. package/Models/DatabaseModels/NetworkDevice.ts +126 -0
  4. package/Server/EnvironmentConfig.ts +47 -16
  5. package/Server/Infrastructure/Postgres/SchemaMigrations/1791700000000-AddMacAddressToNetworkDevice.ts +25 -0
  6. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  7. package/Server/Infrastructure/Redis.ts +8 -8
  8. package/Server/Infrastructure/Status.ts +10 -4
  9. package/Server/Services/DatabaseService.ts +65 -13
  10. package/Server/Services/InventoryItemService.ts +31 -1
  11. package/Server/Services/MonitorTemplateService.ts +140 -19
  12. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +349 -41
  13. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +87 -2
  14. package/Server/Services/NetworkDeviceService.ts +69 -0
  15. package/Server/Services/UserNotificationRuleService.ts +76 -25
  16. package/Server/Types/Database/Permissions/ReadPermission.ts +45 -5
  17. package/Server/Types/Database/QueryUtil.ts +56 -0
  18. package/Server/Types/Markdown.ts +93 -1
  19. package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +82 -17
  20. package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +10 -1
  21. package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +2 -2
  22. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +82 -35
  23. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +31 -5
  24. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +202 -37
  25. package/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.ts +82 -9
  26. package/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.ts +16 -7
  27. package/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.ts +29 -17
  28. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +107 -48
  29. package/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.ts +158 -0
  30. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +27 -0
  31. package/Server/Utils/Telemetry/EntityRegistry.ts +11 -1
  32. package/Server/Utils/Telemetry/TelemetryEntity.ts +83 -9
  33. package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +32 -0
  34. package/Tests/App/Dashboard/AdoptedDeviceDrawer.test.tsx +374 -0
  35. package/Tests/App/Dashboard/DashboardLabelVariables.test.tsx +580 -0
  36. package/Tests/App/Dashboard/DashboardMonitorLabelVariable.test.tsx +438 -0
  37. package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +5 -2
  38. package/Tests/App/Dashboard/DeviceAttachmentCard.test.tsx +273 -0
  39. package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +505 -0
  40. package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +163 -0
  41. package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +401 -0
  42. package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +232 -0
  43. package/Tests/App/Dashboard/InventoryItems.test.tsx +201 -0
  44. package/Tests/App/Dashboard/InventoryTypeAndStatusFacets.test.tsx +798 -0
  45. package/Tests/App/Dashboard/NetworkTopologyLiveView.test.tsx +320 -0
  46. package/Tests/App/Dashboard/NetworkTopologyToolbar.test.tsx +275 -0
  47. package/Tests/App/Dashboard/OnCallCalendarFeedEmptyState.test.tsx +975 -0
  48. package/Tests/App/Dashboard/OnCallCalendarFeedPlanGate.test.tsx +63 -0
  49. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +626 -0
  50. package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +348 -0
  51. package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +331 -0
  52. package/Tests/App/Dashboard/UserSettingsEmailPreferences.test.tsx +603 -0
  53. package/Tests/App/Dashboard/UserSettingsNotificationSettings.test.tsx +324 -0
  54. package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +13 -4
  55. package/Tests/App/StatusPage/StatusPageOidcOrigin.test.tsx +223 -0
  56. package/Tests/Models/InventoryItemStatus.test.ts +147 -0
  57. package/Tests/Models/NetworkDeviceMacAddressColumn.test.ts +294 -0
  58. package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +129 -0
  59. package/Tests/Server/EnvironmentConfigValkey.test.ts +227 -0
  60. package/Tests/Server/Infrastructure/Postgres/AddMacAddressToNetworkDeviceMigration.test.ts +365 -0
  61. package/Tests/Server/Infrastructure/Postgres/CustomFieldValueMappingMigration.test.ts +62 -23
  62. package/Tests/Server/Infrastructure/ValkeyDeploymentConfig.test.ts +265 -0
  63. package/Tests/Server/Middleware/HttpMetricsMiddleware.test.ts +382 -0
  64. package/Tests/Server/Middleware/SCIMAuthorization.test.ts +525 -0
  65. package/Tests/Server/Services/DatabaseServiceAggregateBy.test.ts +291 -56
  66. package/Tests/Server/Services/DatabaseServiceSortTiebreaker.test.ts +151 -0
  67. package/Tests/Server/Services/InventoryItemManualCreate.test.ts +105 -0
  68. package/Tests/Server/Services/InventoryItemPromotionGate.test.ts +178 -0
  69. package/Tests/Server/Services/MonitorTemplateServiceCustomFieldSync.test.ts +502 -0
  70. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +1133 -81
  71. package/Tests/Server/Services/NetworkDeviceDiscoveryScanRegistration.test.ts +520 -0
  72. package/Tests/Server/Services/NetworkDeviceMacAddressNormalization.test.ts +572 -0
  73. package/Tests/Server/Types/Database/InventoryStatusPostgres.test.ts +368 -0
  74. package/Tests/Server/Types/Database/Permissions/ReadBlockPermission.test.ts +261 -14
  75. package/Tests/Server/Types/Database/QueryUtilIncludesAnyOfGroups.test.ts +169 -0
  76. package/Tests/Server/Types/Database/QueryUtilIncludesAnyOfGroupsPostgres.test.ts +297 -0
  77. package/Tests/Server/Types/Markdown.test.ts +194 -1
  78. package/Tests/Server/Types/Workflow/Components/IncomingWebhookUtils.test.ts +279 -0
  79. package/Tests/Server/Types/Workflow/Components/TextToJson.test.ts +212 -0
  80. package/Tests/Server/Utils/CustomField/CustomFieldMappingRegistry.test.ts +436 -0
  81. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +214 -0
  82. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1 -1
  83. package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +10 -3
  84. package/Tests/Server/Utils/EventLoop.test.ts +359 -0
  85. package/Tests/Server/Utils/JsonWebToken.test.ts +30 -0
  86. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteria.test.ts +242 -0
  87. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteriaAggregation.test.ts +13 -7
  88. package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +29 -0
  89. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +30 -6
  90. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +246 -0
  91. package/Tests/Server/Utils/Monitor/MonitorCriteriaEmailEvalLogAgreement.test.ts +280 -0
  92. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +224 -10
  93. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +570 -0
  94. package/Tests/Server/Utils/Monitor/MonitorCriteriaExpectationBuilderUnits.test.ts +30 -5
  95. package/Tests/Server/Utils/Monitor/MonitorCriteriaMessageBuilderUnits.test.ts +68 -21
  96. package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +36 -19
  97. package/Tests/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.test.ts +573 -0
  98. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +317 -0
  99. package/Tests/Server/Utils/Telemetry/ContextSpanProcessor.test.ts +281 -0
  100. package/Tests/Server/Utils/Telemetry/InventoryDuplicateIdentity.test.ts +316 -0
  101. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +111 -8
  102. package/Tests/Types/Database/IncludesAnyOfGroups.test.ts +106 -0
  103. package/Tests/Types/JSONFunctions.test.ts +40 -0
  104. package/Tests/Types/NetworkAutomation/AutoImportRunMerge.test.ts +235 -0
  105. package/Tests/Types/NetworkAutomation/RuleRunResult.test.ts +66 -0
  106. package/Tests/Types/NetworkAutomation/RuleRunResultDescribe.test.ts +309 -1
  107. package/Tests/Types/Telemetry/InventoryLiveness.test.ts +99 -0
  108. package/Tests/UI/Components/CustomFields/CustomFieldsDetail.test.tsx +160 -0
  109. package/Tests/UI/ReactRouterSingletonBuild.test.ts +133 -0
  110. package/Tests/UI/Rum/ReplayHeader.test.tsx +10 -2
  111. package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +514 -0
  112. package/Tests/UI/Rum/ReplayTimeFormat.test.ts +94 -0
  113. package/Tests/UI/Rum/ReplayUi.test.tsx +559 -0
  114. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +5 -0
  115. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +1 -0
  116. package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +11 -1
  117. package/Tests/Utils/Dashboard/LabelVariable.test.ts +257 -0
  118. package/Tests/Utils/Dashboard/VariableUrlState.test.ts +144 -14
  119. package/Tests/Utils/MetricUnitUtil.test.ts +81 -0
  120. package/Tests/Utils/Monitor/DeviceMacLearningUtil.test.ts +497 -0
  121. package/Tests/Utils/Monitor/MetricValueFormatter.test.ts +546 -0
  122. package/Tests/Utils/Monitor/MonitorTemplateCustomFieldUtil.test.ts +218 -0
  123. package/Tests/Utils/Monitor/NetworkTopologyEndpointAdoption.test.ts +1755 -0
  124. package/Tests/Utils/NetworkAutomation/AutoImportRunChain.test.ts +320 -0
  125. package/Types/BaseDatabase/IncludesAnyOfGroups.ts +77 -0
  126. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
  127. package/Types/Dashboard/DashboardComponents/DashboardMonitorListComponent.ts +1 -0
  128. package/Types/Dashboard/DashboardVariable.ts +8 -0
  129. package/Types/JSON.ts +4 -0
  130. package/Types/JSONFunctions.ts +16 -0
  131. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +13 -0
  132. package/Types/NetworkAutomation/RuleRunResult.ts +402 -13
  133. package/Types/SerializableObjectDictionary.ts +4 -0
  134. package/Types/Telemetry/InventoryLiveness.ts +56 -0
  135. package/UI/Components/CSVFileUpload/CSVFileUpload.tsx +9 -2
  136. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +46 -21
  137. package/UI/Components/Dashboard/DashboardVariableControl.tsx +285 -0
  138. package/UI/esbuild-config.js +6 -0
  139. package/Utils/Dashboard/Components/DashboardMonitorListComponent.ts +12 -1
  140. package/Utils/Dashboard/LabelVariable.ts +152 -0
  141. package/Utils/Dashboard/VariableUrlState.ts +27 -5
  142. package/Utils/MetricUnitUtil.ts +34 -0
  143. package/Utils/Monitor/DeviceMacLearningUtil.ts +177 -0
  144. package/Utils/Monitor/MetricValueFormatter.ts +342 -0
  145. package/Utils/Monitor/MonitorTemplateCustomFieldUtil.ts +124 -0
  146. package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +7 -2
  147. package/Utils/Monitor/NetworkTopologyUtil.ts +693 -0
  148. package/Utils/NetworkAutomation/AutoImportRunChain.ts +138 -0
  149. package/build/dist/Models/DatabaseModels/GlobalConfig.js +12 -12
  150. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  151. package/build/dist/Models/DatabaseModels/InventoryItem.js +34 -1
  152. package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -1
  153. package/build/dist/Models/DatabaseModels/NetworkDevice.js +128 -0
  154. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  155. package/build/dist/Server/EnvironmentConfig.js +44 -12
  156. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  157. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791700000000-AddMacAddressToNetworkDevice.js +14 -0
  158. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791700000000-AddMacAddressToNetworkDevice.js.map +1 -0
  159. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  160. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  161. package/build/dist/Server/Infrastructure/Redis.js +8 -8
  162. package/build/dist/Server/Infrastructure/Redis.js.map +1 -1
  163. package/build/dist/Server/Infrastructure/Status.js +10 -4
  164. package/build/dist/Server/Infrastructure/Status.js.map +1 -1
  165. package/build/dist/Server/Services/DatabaseService.js +58 -13
  166. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  167. package/build/dist/Server/Services/InventoryItemService.js +28 -1
  168. package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
  169. package/build/dist/Server/Services/MonitorTemplateService.js +116 -17
  170. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  171. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +270 -37
  172. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  173. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +65 -0
  174. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  175. package/build/dist/Server/Services/NetworkDeviceService.js +54 -0
  176. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  177. package/build/dist/Server/Services/UserNotificationRuleService.js +60 -25
  178. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  179. package/build/dist/Server/Types/Database/Permissions/ReadPermission.js +29 -4
  180. package/build/dist/Server/Types/Database/Permissions/ReadPermission.js.map +1 -1
  181. package/build/dist/Server/Types/Database/QueryUtil.js +36 -0
  182. package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
  183. package/build/dist/Server/Types/Markdown.js +75 -0
  184. package/build/dist/Server/Types/Markdown.js.map +1 -1
  185. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +53 -18
  186. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
  187. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +10 -1
  188. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -1
  189. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +2 -2
  190. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -1
  191. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +58 -35
  192. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  193. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +29 -5
  194. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
  195. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +166 -35
  196. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  197. package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js +58 -9
  198. package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js.map +1 -1
  199. package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.js +9 -3
  200. package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.js.map +1 -1
  201. package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.js +26 -12
  202. package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.js.map +1 -1
  203. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +74 -33
  204. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  205. package/build/dist/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.js +114 -0
  206. package/build/dist/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.js.map +1 -0
  207. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +25 -0
  208. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  209. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +9 -1
  210. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  211. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +70 -13
  212. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  213. package/build/dist/Types/BaseDatabase/IncludesAnyOfGroups.js +54 -0
  214. package/build/dist/Types/BaseDatabase/IncludesAnyOfGroups.js.map +1 -0
  215. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
  216. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  217. package/build/dist/Types/Dashboard/DashboardVariable.js +1 -0
  218. package/build/dist/Types/Dashboard/DashboardVariable.js.map +1 -1
  219. package/build/dist/Types/JSON.js +1 -0
  220. package/build/dist/Types/JSON.js.map +1 -1
  221. package/build/dist/Types/JSONFunctions.js +13 -0
  222. package/build/dist/Types/JSONFunctions.js.map +1 -1
  223. package/build/dist/Types/NetworkAutomation/RuleRunResult.js +291 -6
  224. package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
  225. package/build/dist/Types/SerializableObjectDictionary.js +4 -0
  226. package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
  227. package/build/dist/Types/Telemetry/InventoryLiveness.js +37 -0
  228. package/build/dist/Types/Telemetry/InventoryLiveness.js.map +1 -0
  229. package/build/dist/UI/Components/CSVFileUpload/CSVFileUpload.js +7 -0
  230. package/build/dist/UI/Components/CSVFileUpload/CSVFileUpload.js.map +1 -1
  231. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +9 -2
  232. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  233. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js +137 -0
  234. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js.map +1 -0
  235. package/build/dist/Utils/Dashboard/Components/DashboardMonitorListComponent.js +9 -1
  236. package/build/dist/Utils/Dashboard/Components/DashboardMonitorListComponent.js.map +1 -1
  237. package/build/dist/Utils/Dashboard/LabelVariable.js +96 -0
  238. package/build/dist/Utils/Dashboard/LabelVariable.js.map +1 -0
  239. package/build/dist/Utils/Dashboard/VariableUrlState.js +19 -4
  240. package/build/dist/Utils/Dashboard/VariableUrlState.js.map +1 -1
  241. package/build/dist/Utils/MetricUnitUtil.js +26 -0
  242. package/build/dist/Utils/MetricUnitUtil.js.map +1 -1
  243. package/build/dist/Utils/Monitor/DeviceMacLearningUtil.js +112 -0
  244. package/build/dist/Utils/Monitor/DeviceMacLearningUtil.js.map +1 -0
  245. package/build/dist/Utils/Monitor/MetricValueFormatter.js +276 -0
  246. package/build/dist/Utils/Monitor/MetricValueFormatter.js.map +1 -0
  247. package/build/dist/Utils/Monitor/MonitorTemplateCustomFieldUtil.js +101 -0
  248. package/build/dist/Utils/Monitor/MonitorTemplateCustomFieldUtil.js.map +1 -0
  249. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +7 -2
  250. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -1
  251. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +484 -0
  252. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  253. package/build/dist/Utils/NetworkAutomation/AutoImportRunChain.js +59 -0
  254. package/build/dist/Utils/NetworkAutomation/AutoImportRunChain.js.map +1 -0
  255. package/jest.config.json +2 -0
  256. package/package.json +1 -1
  257. package/test-setup.sh +9 -9
  258. package/tsconfig.json +51 -11
  259. package/Tests/App/Dashboard/NotificationEmailPreferences.test.tsx +0 -399
@@ -0,0 +1,580 @@
1
+ import "@testing-library/jest-dom";
2
+ import React from "react";
3
+ import {
4
+ afterEach,
5
+ beforeEach,
6
+ describe,
7
+ expect,
8
+ jest,
9
+ test,
10
+ } from "@jest/globals";
11
+ import {
12
+ cleanup,
13
+ fireEvent,
14
+ render,
15
+ screen,
16
+ waitFor,
17
+ } from "@testing-library/react";
18
+ import DashboardVariable, {
19
+ DashboardVariableOption,
20
+ DashboardVariableType,
21
+ } from "../../../Types/Dashboard/DashboardVariable";
22
+ import ObjectID from "../../../Types/ObjectID";
23
+ import { VariableValueChange } from "../../../UI/Components/Dashboard/DashboardVariableControl";
24
+ import getJestMockFunction, { MockFunction } from "../../MockType";
25
+ import PrivateSelector from "../../../../App/FeatureSet/Dashboard/src/Components/Dashboard/Toolbar/DashboardVariableSelector";
26
+ import PublicSelector from "../../../../App/FeatureSet/PublicDashboard/src/Pages/DashboardView/DashboardVariableSelector";
27
+ import DashboardVariablesModal from "../../../../App/FeatureSet/Dashboard/src/Components/Dashboard/Toolbar/DashboardVariablesModal";
28
+ import ProjectLabelVariableDropdown from "../../../../App/FeatureSet/Dashboard/src/Components/Dashboard/Canvas/ProjectLabelVariableDropdown";
29
+ import ComponentInputTypeToFormFieldType from "../../../../App/FeatureSet/Dashboard/src/Components/Dashboard/Canvas/ComponentInputTypeToFormFieldType";
30
+ import { ComponentInputType } from "../../../Types/Dashboard/DashboardComponents/ComponentArgument";
31
+ import FormFieldSchemaType from "../../../UI/Components/Forms/Types/FormFieldSchemaType";
32
+ import DashboardVariableUrlState from "../../../Utils/Dashboard/VariableUrlState";
33
+ import DashboardVariableInterpolation from "../../../Utils/Dashboard/VariableInterpolation";
34
+
35
+ const getListMock: MockFunction = getJestMockFunction();
36
+ const telemetryMock: MockFunction = getJestMockFunction();
37
+ const publicPostMock: MockFunction = getJestMockFunction();
38
+
39
+ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
40
+ return {
41
+ __esModule: true,
42
+ default: {
43
+ getList: (...args: Array<unknown>): unknown => {
44
+ return getListMock(...args);
45
+ },
46
+ },
47
+ };
48
+ });
49
+ jest.mock("../../../UI/Utils/Project", () => {
50
+ return {
51
+ __esModule: true,
52
+ default: {
53
+ getCurrentProjectId: (): string => {
54
+ return "44444444-4444-4444-8444-444444444444";
55
+ },
56
+ },
57
+ };
58
+ });
59
+ jest.mock(
60
+ "../../../../App/FeatureSet/Dashboard/src/Components/Metrics/Utils/Metrics",
61
+ () => {
62
+ return {
63
+ __esModule: true,
64
+ default: {
65
+ getTelemetryAttributeValues: (...args: Array<unknown>): unknown => {
66
+ return telemetryMock(...args);
67
+ },
68
+ },
69
+ };
70
+ },
71
+ );
72
+ jest.mock("../../../../App/FeatureSet/PublicDashboard/src/Utils/API", () => {
73
+ return {
74
+ __esModule: true,
75
+ default: {
76
+ post: (...args: Array<unknown>): unknown => {
77
+ return publicPostMock(...args);
78
+ },
79
+ },
80
+ };
81
+ });
82
+
83
+ const OPTIONS: Array<DashboardVariableOption> = [
84
+ { label: "0660", value: "11111111-1111-4111-8111-111111111111" },
85
+ { label: "0661", value: "22222222-2222-4222-8222-222222222222" },
86
+ ];
87
+ const FIRST: string = OPTIONS[0]!.value;
88
+ const SECOND: string = OPTIONS[1]!.value;
89
+ const DASHBOARD_ID: ObjectID = new ObjectID(
90
+ "33333333-3333-4333-8333-333333333333",
91
+ );
92
+
93
+ function labelVariable(
94
+ overrides: Partial<DashboardVariable> = {},
95
+ ): DashboardVariable {
96
+ return {
97
+ id: "unit",
98
+ name: "UNIT",
99
+ label: "Unit",
100
+ type: DashboardVariableType.ProjectLabel,
101
+ labelOptions: OPTIONS,
102
+ ...overrides,
103
+ };
104
+ }
105
+
106
+ interface SelectorState {
107
+ variable: DashboardVariable;
108
+ changes: Array<VariableValueChange>;
109
+ }
110
+
111
+ function renderSelector(
112
+ isPublic: boolean,
113
+ variable: DashboardVariable,
114
+ ): SelectorState {
115
+ const state: SelectorState = { variable, changes: [] };
116
+ const Harness: React.FunctionComponent = (): React.ReactElement => {
117
+ const [current, setCurrent] = React.useState<DashboardVariable>(variable);
118
+ const onChange: (id: string, change: VariableValueChange) => void = (
119
+ _id: string,
120
+ change: VariableValueChange,
121
+ ): void => {
122
+ const next: DashboardVariable = {
123
+ ...current,
124
+ selectedValue: change.selectedValue,
125
+ selectedValues: change.selectedValues,
126
+ };
127
+ state.variable = next;
128
+ state.changes.push(change);
129
+ setCurrent(next);
130
+ };
131
+ return isPublic ? (
132
+ <PublicSelector
133
+ variables={[current]}
134
+ dashboardId={DASHBOARD_ID}
135
+ onVariableValueChange={onChange}
136
+ />
137
+ ) : (
138
+ <PrivateSelector variables={[current]} onVariableValueChange={onChange} />
139
+ );
140
+ };
141
+ render(<Harness />);
142
+ return state;
143
+ }
144
+
145
+ beforeEach(() => {
146
+ getListMock.mockReset();
147
+ getListMock.mockResolvedValue({
148
+ data: OPTIONS.map((option: DashboardVariableOption) => {
149
+ return {
150
+ _id: option.value,
151
+ name: option.label,
152
+ };
153
+ }),
154
+ count: 2,
155
+ skip: 0,
156
+ limit: 1000,
157
+ });
158
+ telemetryMock.mockReset();
159
+ publicPostMock.mockReset();
160
+ });
161
+ afterEach(cleanup);
162
+
163
+ describe.each([false, true])(
164
+ "Project Labels selector (public=%s)",
165
+ (isPublic: boolean) => {
166
+ test("shows names with leading zeroes and sends stable label IDs without a labels request", () => {
167
+ const state: SelectorState = renderSelector(isPublic, labelVariable());
168
+ expect(screen.getByRole("option", { name: "0660" })).toHaveValue(FIRST);
169
+ fireEvent.change(screen.getByRole("combobox", { name: "Unit" }), {
170
+ target: { value: FIRST },
171
+ });
172
+ expect(state.variable.selectedValue).toBe(FIRST);
173
+ expect(screen.getByRole("combobox", { name: "Unit" })).toHaveValue(FIRST);
174
+ expect(getListMock).not.toHaveBeenCalled();
175
+ expect(telemetryMock).not.toHaveBeenCalled();
176
+ expect(publicPostMock).not.toHaveBeenCalled();
177
+ });
178
+
179
+ test("All remains selected after clearing a configured default", () => {
180
+ const state: SelectorState = renderSelector(
181
+ isPublic,
182
+ labelVariable({ defaultValue: FIRST }),
183
+ );
184
+ const select: HTMLElement = screen.getByRole("combobox", {
185
+ name: "Unit",
186
+ });
187
+ expect(select).toHaveValue(FIRST);
188
+ fireEvent.change(select, { target: { value: "" } });
189
+ expect(state.variable.selectedValue).toBe("");
190
+ expect(select).toHaveValue("");
191
+ });
192
+
193
+ test("multiple choices and Clear update selectedValues and remove stale scalar state", () => {
194
+ const state: SelectorState = renderSelector(
195
+ isPublic,
196
+ labelVariable({
197
+ isMultiSelect: true,
198
+ selectedValue: FIRST,
199
+ defaultValue: FIRST,
200
+ }),
201
+ );
202
+ const button: HTMLElement = screen.getByRole("button", {
203
+ name: /^Unit:/,
204
+ });
205
+ expect(button).toHaveTextContent("All");
206
+ fireEvent.click(button);
207
+ fireEvent.click(screen.getByRole("checkbox", { name: "0660" }));
208
+ expect(button).toHaveTextContent("0660");
209
+ fireEvent.click(screen.getByRole("checkbox", { name: "0661" }));
210
+ expect(state.variable.selectedValues).toEqual([FIRST, SECOND]);
211
+ expect(state.variable.selectedValue).toBeUndefined();
212
+ fireEvent.click(screen.getByRole("button", { name: "Clear" }));
213
+ expect(state.variable.selectedValues).toEqual([]);
214
+ expect(button).toHaveTextContent("All");
215
+ });
216
+
217
+ test("a deleted or disallowed selected ID is visibly unavailable instead of appearing as All", () => {
218
+ renderSelector(isPublic, labelVariable({ selectedValue: "missing" }));
219
+ expect(
220
+ screen.getByRole("option", { name: "Unavailable label" }),
221
+ ).toHaveValue("missing");
222
+ expect(screen.getByRole("combobox", { name: "Unit" })).toHaveValue(
223
+ "missing",
224
+ );
225
+ });
226
+
227
+ test("limits explicit multi-selection to 100 labels", () => {
228
+ const options: Array<DashboardVariableOption> = Array.from(
229
+ { length: 101 },
230
+ (_unused: unknown, index: number) => {
231
+ return {
232
+ label: `Unit ${index}`,
233
+ value: `label-${index}`,
234
+ };
235
+ },
236
+ );
237
+ renderSelector(
238
+ isPublic,
239
+ labelVariable({
240
+ isMultiSelect: true,
241
+ labelOptions: options,
242
+ selectedValues: options
243
+ .slice(0, 100)
244
+ .map((option: DashboardVariableOption) => {
245
+ return option.value;
246
+ }),
247
+ }),
248
+ );
249
+ fireEvent.click(screen.getByRole("button", { name: /^Unit:/ }));
250
+ expect(screen.getByRole("checkbox", { name: "Unit 100" })).toBeDisabled();
251
+ expect(
252
+ screen.getByRole("checkbox", { name: "Unit 0" }),
253
+ ).not.toBeDisabled();
254
+ expect(screen.getByText("Choose up to 100 labels.")).toBeInTheDocument();
255
+ });
256
+ },
257
+ );
258
+
259
+ function renderEditor(
260
+ variable: DashboardVariable,
261
+ ): Array<Array<DashboardVariable>> {
262
+ const saved: Array<Array<DashboardVariable>> = [];
263
+ render(
264
+ <DashboardVariablesModal
265
+ variables={[variable]}
266
+ telemetryAttributeOptions={["host.name"]}
267
+ onSave={(values: Array<DashboardVariable>) => {
268
+ saved.push(values);
269
+ }}
270
+ onClose={() => {}}
271
+ />,
272
+ );
273
+ return saved;
274
+ }
275
+
276
+ function chooseDropdown(name: string, option: string): void {
277
+ fireEvent.keyDown(screen.getByRole("combobox", { name }), {
278
+ key: "ArrowDown",
279
+ });
280
+ fireEvent.click(screen.getByRole("option", { name: option }));
281
+ }
282
+
283
+ describe("Project Labels variable authoring", () => {
284
+ test("switching sources clears incompatible settings and preserves the variable ID", () => {
285
+ const saved: Array<Array<DashboardVariable>> = renderEditor(
286
+ labelVariable({
287
+ type: DashboardVariableType.CustomList,
288
+ customListValues: "0660, 0661",
289
+ isMultiSelect: true,
290
+ selectedValues: ["0660"],
291
+ }),
292
+ );
293
+ chooseDropdown("Variable source", "Text Input");
294
+ fireEvent.click(screen.getByTestId("modal-footer-submit-button"));
295
+ expect(saved[0]?.[0]).toMatchObject({
296
+ id: "unit",
297
+ type: DashboardVariableType.TextInput,
298
+ isMultiSelect: false,
299
+ });
300
+ expect(saved[0]?.[0]).not.toHaveProperty("selectedValue");
301
+ expect(saved[0]?.[0]).not.toHaveProperty("selectedValues");
302
+ expect(saved[0]?.[0]?.customListValues).toBeUndefined();
303
+ expect(saved[0]?.[0]?.labelOptions).toBeUndefined();
304
+ expect(getListMock).not.toHaveBeenCalled();
305
+ });
306
+
307
+ test("clears a default and selection when its label is removed from the allowlist", async () => {
308
+ const saved: Array<Array<DashboardVariable>> = renderEditor(
309
+ labelVariable({ defaultValue: SECOND, selectedValue: SECOND }),
310
+ );
311
+ await screen.findByRole("combobox", { name: "Allowed project labels" });
312
+ fireEvent.keyDown(
313
+ screen.getByRole("combobox", { name: "Allowed project labels" }),
314
+ { key: "Backspace", keyCode: 8 },
315
+ );
316
+ expect(screen.getByRole("combobox", { name: "Default label" })).toHaveValue(
317
+ "",
318
+ );
319
+ fireEvent.click(screen.getByTestId("modal-footer-submit-button"));
320
+ expect(saved[0]?.[0]).toMatchObject({
321
+ labelOptions: [OPTIONS[0]],
322
+ defaultValue: "",
323
+ });
324
+ expect(saved[0]?.[0]).not.toHaveProperty("selectedValue");
325
+ expect(saved[0]?.[0]).not.toHaveProperty("selectedValues");
326
+ });
327
+
328
+ test("shows an invalid saved default and requires an explicit valid choice", async () => {
329
+ renderEditor(labelVariable({ defaultValue: "missing" }));
330
+ await screen.findByRole("combobox", { name: "Allowed project labels" });
331
+ const select: HTMLElement = screen.getByRole("combobox", {
332
+ name: "Default label",
333
+ });
334
+ expect(select).toHaveValue("missing");
335
+ expect(screen.getByTestId("modal-footer-submit-button")).toBeDisabled();
336
+ fireEvent.change(select, { target: { value: "" } });
337
+ expect(screen.getByTestId("modal-footer-submit-button")).not.toBeDisabled();
338
+ });
339
+
340
+ test("creates an explicit allowlist and saves display labels separately from IDs", async () => {
341
+ const saved: Array<Array<DashboardVariable>> = renderEditor(
342
+ labelVariable({
343
+ type: DashboardVariableType.TelemetryAttribute,
344
+ labelOptions: undefined,
345
+ }),
346
+ );
347
+ expect(getListMock).not.toHaveBeenCalled();
348
+ chooseDropdown("Variable source", "Project Labels");
349
+ expect(screen.getByTestId("modal-footer-submit-button")).toBeDisabled();
350
+ await screen.findByRole("combobox", { name: "Allowed project labels" });
351
+ chooseDropdown("Allowed project labels", "0660");
352
+ fireEvent.change(screen.getByRole("combobox", { name: "Default label" }), {
353
+ target: { value: FIRST },
354
+ });
355
+ fireEvent.click(screen.getByTestId("modal-footer-submit-button"));
356
+ expect(saved[0]?.[0]).toMatchObject({
357
+ id: "unit",
358
+ type: DashboardVariableType.ProjectLabel,
359
+ labelOptions: [OPTIONS[0]],
360
+ defaultValue: FIRST,
361
+ });
362
+ expect(getListMock.mock.calls[0]?.[0]).toMatchObject({
363
+ query: { projectId: "44444444-4444-4444-8444-444444444444" },
364
+ select: { _id: true, name: true },
365
+ limit: 1000,
366
+ });
367
+ });
368
+
369
+ test("keeps a saved label snapshot when no currently available project label has its ID", async () => {
370
+ getListMock.mockResolvedValue({ data: [], count: 0, skip: 0, limit: 1000 });
371
+ const saved: Array<Array<DashboardVariable>> = renderEditor(
372
+ labelVariable({ defaultValue: FIRST }),
373
+ );
374
+ await screen.findByRole("combobox", { name: "Allowed project labels" });
375
+ fireEvent.click(screen.getByTestId("modal-footer-submit-button"));
376
+ expect(saved[0]?.[0]?.labelOptions).toEqual(OPTIONS);
377
+ expect(saved[0]?.[0]?.defaultValue).toBe(FIRST);
378
+ });
379
+
380
+ test.each([false, true])(
381
+ "a newly configured default applies after a clean reload (public=%s)",
382
+ async (isPublic: boolean) => {
383
+ const saved: Array<Array<DashboardVariable>> = renderEditor(
384
+ labelVariable({
385
+ type: DashboardVariableType.TelemetryAttribute,
386
+ labelOptions: undefined,
387
+ }),
388
+ );
389
+ chooseDropdown("Variable source", "Project Labels");
390
+ await screen.findByRole("combobox", { name: "Allowed project labels" });
391
+ chooseDropdown("Allowed project labels", "0660");
392
+ fireEvent.change(
393
+ screen.getByRole("combobox", { name: "Default label" }),
394
+ {
395
+ target: { value: FIRST },
396
+ },
397
+ );
398
+ fireEvent.click(screen.getByTestId("modal-footer-submit-button"));
399
+ expect(saved[0]?.[0]).not.toHaveProperty("selectedValue");
400
+ expect(saved[0]?.[0]).not.toHaveProperty("selectedValues");
401
+
402
+ // Reload the JSON definition without any viewer-specific URL selection.
403
+ const stored: Array<DashboardVariable> = JSON.parse(
404
+ JSON.stringify(saved[0]),
405
+ );
406
+ const [restored]: Array<DashboardVariable> =
407
+ DashboardVariableUrlState.applyUrlToVariables(
408
+ stored,
409
+ DashboardVariableUrlState.parseFromSearch(""),
410
+ );
411
+ cleanup();
412
+ renderSelector(isPublic, restored!);
413
+ expect(screen.getByRole("combobox", { name: "Unit" })).toHaveValue(FIRST);
414
+ expect(DashboardVariableInterpolation.resolveValue(restored!)).toEqual({
415
+ scalar: FIRST,
416
+ });
417
+ },
418
+ );
419
+
420
+ test.each([false, true])(
421
+ "saving definition edits does not publish runtime selections (multi=%s)",
422
+ async (isMultiSelect: boolean) => {
423
+ const original: DashboardVariable = labelVariable({
424
+ isMultiSelect,
425
+ defaultValue: FIRST,
426
+ selectedValue: SECOND,
427
+ selectedValues: [SECOND],
428
+ });
429
+ const saved: Array<Array<DashboardVariable>> = renderEditor(original);
430
+ await screen.findByRole("combobox", { name: "Allowed project labels" });
431
+ fireEvent.click(screen.getByTestId("modal-footer-submit-button"));
432
+ expect(saved[0]?.[0]).not.toHaveProperty("selectedValue");
433
+ expect(saved[0]?.[0]).not.toHaveProperty("selectedValues");
434
+ expect(original.selectedValue).toBe(SECOND);
435
+ expect(original.selectedValues).toEqual([SECOND]);
436
+
437
+ const stored: Array<DashboardVariable> = JSON.parse(
438
+ JSON.stringify(saved[0]),
439
+ );
440
+ expect(DashboardVariableInterpolation.resolveValue(stored[0]!)).toEqual(
441
+ isMultiSelect ? undefined : { scalar: FIRST },
442
+ );
443
+ },
444
+ );
445
+
446
+ test("loads additional project label pages so choices beyond the first page are available", async () => {
447
+ getListMock.mockResolvedValueOnce({
448
+ data: [{ _id: FIRST, name: "0660" }],
449
+ count: 2,
450
+ skip: 0,
451
+ limit: 1000,
452
+ });
453
+ getListMock.mockResolvedValueOnce({
454
+ data: [{ _id: SECOND, name: "0661" }],
455
+ count: 2,
456
+ skip: 1,
457
+ limit: 1000,
458
+ });
459
+ renderEditor(labelVariable({ labelOptions: [] }));
460
+ await screen.findByRole("combobox", { name: "Allowed project labels" });
461
+ chooseDropdown("Allowed project labels", "0661");
462
+ expect(getListMock).toHaveBeenCalledTimes(2);
463
+ expect(getListMock.mock.calls[1]?.[0]).toMatchObject({ skip: 1 });
464
+ expect(screen.getByRole("option", { name: "0661" })).toHaveValue(SECOND);
465
+ });
466
+
467
+ test("reports a labels loading failure and prevents saving an empty allowlist", async () => {
468
+ getListMock.mockRejectedValue(new Error("Labels could not be loaded"));
469
+ const saved: Array<Array<DashboardVariable>> = renderEditor(
470
+ labelVariable({ labelOptions: [] }),
471
+ );
472
+ await waitFor(() => {
473
+ return expect(screen.queryByText("Loading project labels…")).toBeNull();
474
+ });
475
+ expect(
476
+ screen.getByText("Choose between 1 and 1,000 allowed labels."),
477
+ ).toBeInTheDocument();
478
+ expect(screen.getByTestId("modal-footer-submit-button")).toBeDisabled();
479
+ expect(saved).toEqual([]);
480
+ });
481
+
482
+ test("disables a single default for multi-select label variables", async () => {
483
+ renderEditor(labelVariable({ isMultiSelect: true, defaultValue: FIRST }));
484
+ await screen.findByRole("combobox", { name: "Allowed project labels" });
485
+ expect(
486
+ screen.getByRole("combobox", { name: "Default label" }),
487
+ ).toBeDisabled();
488
+ });
489
+
490
+ test("preserves legacy custom-list source and values when saving unrelated edits", () => {
491
+ const saved: Array<Array<DashboardVariable>> = renderEditor(
492
+ labelVariable({
493
+ type: DashboardVariableType.CustomList,
494
+ labelOptions: undefined,
495
+ customListValues: "0660, 0661",
496
+ defaultValue: "0660",
497
+ }),
498
+ );
499
+ fireEvent.click(screen.getByTestId("modal-footer-submit-button"));
500
+ expect(saved[0]?.[0]).toMatchObject({
501
+ type: DashboardVariableType.CustomList,
502
+ customListValues: "0660, 0661",
503
+ defaultValue: "0660",
504
+ });
505
+ expect(getListMock).not.toHaveBeenCalled();
506
+ });
507
+ });
508
+
509
+ describe("Monitor List variable binding editor", () => {
510
+ test("offers only label variables and persists their stable IDs across renames", () => {
511
+ const changes: Array<string> = [];
512
+ const { rerender } = render(
513
+ <ProjectLabelVariableDropdown
514
+ variables={[
515
+ labelVariable(),
516
+ labelVariable({
517
+ id: "telemetry",
518
+ name: "host",
519
+ type: DashboardVariableType.TelemetryAttribute,
520
+ }),
521
+ ]}
522
+ onChange={(value: string) => {
523
+ changes.push(value);
524
+ }}
525
+ />,
526
+ );
527
+ expect(screen.queryByRole("option", { name: "host" })).toBeNull();
528
+ fireEvent.change(screen.getByRole("combobox", { name: "Label Variable" }), {
529
+ target: { value: "unit" },
530
+ });
531
+ expect(changes).toEqual(["unit"]);
532
+ rerender(
533
+ <ProjectLabelVariableDropdown
534
+ variables={[labelVariable({ name: "LOCATION" })]}
535
+ value="unit"
536
+ onChange={() => {}}
537
+ />,
538
+ );
539
+ expect(screen.getByRole("combobox")).toHaveValue("unit");
540
+ expect(
541
+ screen.getByRole("option", { name: "Unit (LOCATION)" }),
542
+ ).toBeInTheDocument();
543
+ });
544
+
545
+ test("flags a deleted binding and lets the author explicitly clear it", () => {
546
+ const changes: Array<string> = [];
547
+ render(
548
+ <ProjectLabelVariableDropdown
549
+ variables={[]}
550
+ value="missing"
551
+ onChange={(value: string) => {
552
+ changes.push(value);
553
+ }}
554
+ />,
555
+ );
556
+ expect(screen.getByRole("alert")).toHaveTextContent(
557
+ "removed or its source changed",
558
+ );
559
+ expect(screen.getByRole("combobox")).toHaveValue("missing");
560
+ fireEvent.change(screen.getByRole("combobox"), { target: { value: "" } });
561
+ expect(changes).toEqual([""]);
562
+ });
563
+
564
+ test("explains how to create a variable when none exists", () => {
565
+ render(<ProjectLabelVariableDropdown onChange={() => {}} />);
566
+ expect(
567
+ screen.getByText(
568
+ "Add a Project Labels variable from the dashboard toolbar to use it here.",
569
+ ),
570
+ ).toBeInTheDocument();
571
+ });
572
+
573
+ test("registers the binding as a custom control instead of a free-text field", () => {
574
+ expect(
575
+ ComponentInputTypeToFormFieldType.getFormFieldTypeByComponentInputType(
576
+ ComponentInputType.ProjectLabelVariable,
577
+ ).fieldType,
578
+ ).toBe(FormFieldSchemaType.CustomComponent);
579
+ });
580
+ });