@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.
- package/Models/DatabaseModels/GlobalConfig.ts +12 -12
- package/Models/DatabaseModels/InventoryItem.ts +44 -1
- package/Models/DatabaseModels/NetworkDevice.ts +126 -0
- package/Server/EnvironmentConfig.ts +47 -16
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791700000000-AddMacAddressToNetworkDevice.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Infrastructure/Redis.ts +8 -8
- package/Server/Infrastructure/Status.ts +10 -4
- package/Server/Services/DatabaseService.ts +65 -13
- package/Server/Services/InventoryItemService.ts +31 -1
- package/Server/Services/MonitorTemplateService.ts +140 -19
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +349 -41
- package/Server/Services/NetworkDeviceDiscoveryScanService.ts +87 -2
- package/Server/Services/NetworkDeviceService.ts +69 -0
- package/Server/Services/UserNotificationRuleService.ts +76 -25
- package/Server/Types/Database/Permissions/ReadPermission.ts +45 -5
- package/Server/Types/Database/QueryUtil.ts +56 -0
- package/Server/Types/Markdown.ts +93 -1
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +82 -17
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +10 -1
- package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +2 -2
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +82 -35
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +31 -5
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +202 -37
- package/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.ts +82 -9
- package/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.ts +16 -7
- package/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.ts +29 -17
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +107 -48
- package/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.ts +158 -0
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +27 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +11 -1
- package/Server/Utils/Telemetry/TelemetryEntity.ts +83 -9
- package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +32 -0
- package/Tests/App/Dashboard/AdoptedDeviceDrawer.test.tsx +374 -0
- package/Tests/App/Dashboard/DashboardLabelVariables.test.tsx +580 -0
- package/Tests/App/Dashboard/DashboardMonitorLabelVariable.test.tsx +438 -0
- package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +5 -2
- package/Tests/App/Dashboard/DeviceAttachmentCard.test.tsx +273 -0
- package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +505 -0
- package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +163 -0
- package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +401 -0
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +232 -0
- package/Tests/App/Dashboard/InventoryItems.test.tsx +201 -0
- package/Tests/App/Dashboard/InventoryTypeAndStatusFacets.test.tsx +798 -0
- package/Tests/App/Dashboard/NetworkTopologyLiveView.test.tsx +320 -0
- package/Tests/App/Dashboard/NetworkTopologyToolbar.test.tsx +275 -0
- package/Tests/App/Dashboard/OnCallCalendarFeedEmptyState.test.tsx +975 -0
- package/Tests/App/Dashboard/OnCallCalendarFeedPlanGate.test.tsx +63 -0
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +626 -0
- package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +348 -0
- package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +331 -0
- package/Tests/App/Dashboard/UserSettingsEmailPreferences.test.tsx +603 -0
- package/Tests/App/Dashboard/UserSettingsNotificationSettings.test.tsx +324 -0
- package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +13 -4
- package/Tests/App/StatusPage/StatusPageOidcOrigin.test.tsx +223 -0
- package/Tests/Models/InventoryItemStatus.test.ts +147 -0
- package/Tests/Models/NetworkDeviceMacAddressColumn.test.ts +294 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +129 -0
- package/Tests/Server/EnvironmentConfigValkey.test.ts +227 -0
- package/Tests/Server/Infrastructure/Postgres/AddMacAddressToNetworkDeviceMigration.test.ts +365 -0
- package/Tests/Server/Infrastructure/Postgres/CustomFieldValueMappingMigration.test.ts +62 -23
- package/Tests/Server/Infrastructure/ValkeyDeploymentConfig.test.ts +265 -0
- package/Tests/Server/Middleware/HttpMetricsMiddleware.test.ts +382 -0
- package/Tests/Server/Middleware/SCIMAuthorization.test.ts +525 -0
- package/Tests/Server/Services/DatabaseServiceAggregateBy.test.ts +291 -56
- package/Tests/Server/Services/DatabaseServiceSortTiebreaker.test.ts +151 -0
- package/Tests/Server/Services/InventoryItemManualCreate.test.ts +105 -0
- package/Tests/Server/Services/InventoryItemPromotionGate.test.ts +178 -0
- package/Tests/Server/Services/MonitorTemplateServiceCustomFieldSync.test.ts +502 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +1133 -81
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanRegistration.test.ts +520 -0
- package/Tests/Server/Services/NetworkDeviceMacAddressNormalization.test.ts +572 -0
- package/Tests/Server/Types/Database/InventoryStatusPostgres.test.ts +368 -0
- package/Tests/Server/Types/Database/Permissions/ReadBlockPermission.test.ts +261 -14
- package/Tests/Server/Types/Database/QueryUtilIncludesAnyOfGroups.test.ts +169 -0
- package/Tests/Server/Types/Database/QueryUtilIncludesAnyOfGroupsPostgres.test.ts +297 -0
- package/Tests/Server/Types/Markdown.test.ts +194 -1
- package/Tests/Server/Types/Workflow/Components/IncomingWebhookUtils.test.ts +279 -0
- package/Tests/Server/Types/Workflow/Components/TextToJson.test.ts +212 -0
- package/Tests/Server/Utils/CustomField/CustomFieldMappingRegistry.test.ts +436 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +214 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1 -1
- package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +10 -3
- package/Tests/Server/Utils/EventLoop.test.ts +359 -0
- package/Tests/Server/Utils/JsonWebToken.test.ts +30 -0
- package/Tests/Server/Utils/Monitor/Criteria/CompareCriteria.test.ts +242 -0
- package/Tests/Server/Utils/Monitor/Criteria/CompareCriteriaAggregation.test.ts +13 -7
- package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +29 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +30 -6
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +246 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEmailEvalLogAgreement.test.ts +280 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +224 -10
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +570 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaExpectationBuilderUnits.test.ts +30 -5
- package/Tests/Server/Utils/Monitor/MonitorCriteriaMessageBuilderUnits.test.ts +68 -21
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +36 -19
- package/Tests/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.test.ts +573 -0
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +317 -0
- package/Tests/Server/Utils/Telemetry/ContextSpanProcessor.test.ts +281 -0
- package/Tests/Server/Utils/Telemetry/InventoryDuplicateIdentity.test.ts +316 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +111 -8
- package/Tests/Types/Database/IncludesAnyOfGroups.test.ts +106 -0
- package/Tests/Types/JSONFunctions.test.ts +40 -0
- package/Tests/Types/NetworkAutomation/AutoImportRunMerge.test.ts +235 -0
- package/Tests/Types/NetworkAutomation/RuleRunResult.test.ts +66 -0
- package/Tests/Types/NetworkAutomation/RuleRunResultDescribe.test.ts +309 -1
- package/Tests/Types/Telemetry/InventoryLiveness.test.ts +99 -0
- package/Tests/UI/Components/CustomFields/CustomFieldsDetail.test.tsx +160 -0
- package/Tests/UI/ReactRouterSingletonBuild.test.ts +133 -0
- package/Tests/UI/Rum/ReplayHeader.test.tsx +10 -2
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +514 -0
- package/Tests/UI/Rum/ReplayTimeFormat.test.ts +94 -0
- package/Tests/UI/Rum/ReplayUi.test.tsx +559 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +5 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +1 -0
- package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +11 -1
- package/Tests/Utils/Dashboard/LabelVariable.test.ts +257 -0
- package/Tests/Utils/Dashboard/VariableUrlState.test.ts +144 -14
- package/Tests/Utils/MetricUnitUtil.test.ts +81 -0
- package/Tests/Utils/Monitor/DeviceMacLearningUtil.test.ts +497 -0
- package/Tests/Utils/Monitor/MetricValueFormatter.test.ts +546 -0
- package/Tests/Utils/Monitor/MonitorTemplateCustomFieldUtil.test.ts +218 -0
- package/Tests/Utils/Monitor/NetworkTopologyEndpointAdoption.test.ts +1755 -0
- package/Tests/Utils/NetworkAutomation/AutoImportRunChain.test.ts +320 -0
- package/Types/BaseDatabase/IncludesAnyOfGroups.ts +77 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardMonitorListComponent.ts +1 -0
- package/Types/Dashboard/DashboardVariable.ts +8 -0
- package/Types/JSON.ts +4 -0
- package/Types/JSONFunctions.ts +16 -0
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +13 -0
- package/Types/NetworkAutomation/RuleRunResult.ts +402 -13
- package/Types/SerializableObjectDictionary.ts +4 -0
- package/Types/Telemetry/InventoryLiveness.ts +56 -0
- package/UI/Components/CSVFileUpload/CSVFileUpload.tsx +9 -2
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +46 -21
- package/UI/Components/Dashboard/DashboardVariableControl.tsx +285 -0
- package/UI/esbuild-config.js +6 -0
- package/Utils/Dashboard/Components/DashboardMonitorListComponent.ts +12 -1
- package/Utils/Dashboard/LabelVariable.ts +152 -0
- package/Utils/Dashboard/VariableUrlState.ts +27 -5
- package/Utils/MetricUnitUtil.ts +34 -0
- package/Utils/Monitor/DeviceMacLearningUtil.ts +177 -0
- package/Utils/Monitor/MetricValueFormatter.ts +342 -0
- package/Utils/Monitor/MonitorTemplateCustomFieldUtil.ts +124 -0
- package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +7 -2
- package/Utils/Monitor/NetworkTopologyUtil.ts +693 -0
- package/Utils/NetworkAutomation/AutoImportRunChain.ts +138 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +12 -12
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/InventoryItem.js +34 -1
- package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +128 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +44 -12
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791700000000-AddMacAddressToNetworkDevice.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791700000000-AddMacAddressToNetworkDevice.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Redis.js +8 -8
- package/build/dist/Server/Infrastructure/Redis.js.map +1 -1
- package/build/dist/Server/Infrastructure/Status.js +10 -4
- package/build/dist/Server/Infrastructure/Status.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +58 -13
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +28 -1
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +116 -17
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +270 -37
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +65 -0
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +54 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +60 -25
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/ReadPermission.js +29 -4
- package/build/dist/Server/Types/Database/Permissions/ReadPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryUtil.js +36 -0
- package/build/dist/Server/Types/Database/QueryUtil.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +75 -0
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +53 -18
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +10 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +2 -2
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +58 -35
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +29 -5
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +166 -35
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js +58 -9
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.js +9 -3
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.js +26 -12
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaMessageFormatter.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +74 -33
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.js +114 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMacLearningUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +25 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +9 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +70 -13
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Types/BaseDatabase/IncludesAnyOfGroups.js +54 -0
- package/build/dist/Types/BaseDatabase/IncludesAnyOfGroups.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardVariable.js +1 -0
- package/build/dist/Types/Dashboard/DashboardVariable.js.map +1 -1
- package/build/dist/Types/JSON.js +1 -0
- package/build/dist/Types/JSON.js.map +1 -1
- package/build/dist/Types/JSONFunctions.js +13 -0
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/NetworkAutomation/RuleRunResult.js +291 -6
- package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
- package/build/dist/Types/SerializableObjectDictionary.js +4 -0
- package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
- package/build/dist/Types/Telemetry/InventoryLiveness.js +37 -0
- package/build/dist/Types/Telemetry/InventoryLiveness.js.map +1 -0
- package/build/dist/UI/Components/CSVFileUpload/CSVFileUpload.js +7 -0
- package/build/dist/UI/Components/CSVFileUpload/CSVFileUpload.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +9 -2
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js +137 -0
- package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardMonitorListComponent.js +9 -1
- package/build/dist/Utils/Dashboard/Components/DashboardMonitorListComponent.js.map +1 -1
- package/build/dist/Utils/Dashboard/LabelVariable.js +96 -0
- package/build/dist/Utils/Dashboard/LabelVariable.js.map +1 -0
- package/build/dist/Utils/Dashboard/VariableUrlState.js +19 -4
- package/build/dist/Utils/Dashboard/VariableUrlState.js.map +1 -1
- package/build/dist/Utils/MetricUnitUtil.js +26 -0
- package/build/dist/Utils/MetricUnitUtil.js.map +1 -1
- package/build/dist/Utils/Monitor/DeviceMacLearningUtil.js +112 -0
- package/build/dist/Utils/Monitor/DeviceMacLearningUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MetricValueFormatter.js +276 -0
- package/build/dist/Utils/Monitor/MetricValueFormatter.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorTemplateCustomFieldUtil.js +101 -0
- package/build/dist/Utils/Monitor/MonitorTemplateCustomFieldUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +7 -2
- package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +484 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkAutomation/AutoImportRunChain.js +59 -0
- package/build/dist/Utils/NetworkAutomation/AutoImportRunChain.js.map +1 -0
- package/jest.config.json +2 -0
- package/package.json +1 -1
- package/test-setup.sh +9 -9
- package/tsconfig.json +51 -11
- package/Tests/App/Dashboard/NotificationEmailPreferences.test.tsx +0 -399
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import Includes from "../../../Types/BaseDatabase/Includes";
|
|
2
|
+
import IncludesAnyOfGroups from "../../../Types/BaseDatabase/IncludesAnyOfGroups";
|
|
3
|
+
import DashboardVariable, {
|
|
4
|
+
DashboardVariableType,
|
|
5
|
+
} from "../../../Types/Dashboard/DashboardVariable";
|
|
6
|
+
import JSONFunctions from "../../../Types/JSONFunctions";
|
|
7
|
+
import DashboardLabelVariable from "../../../Utils/Dashboard/LabelVariable";
|
|
8
|
+
|
|
9
|
+
const UNIT_660: string = "06600000-0000-4000-8000-000000000000";
|
|
10
|
+
const UNIT_661: string = "06610000-0000-4000-8000-000000000000";
|
|
11
|
+
const NETWORK: string = "00000000-0000-4000-8000-000000000001";
|
|
12
|
+
|
|
13
|
+
function variable(
|
|
14
|
+
overrides: Partial<DashboardVariable> = {},
|
|
15
|
+
): DashboardVariable {
|
|
16
|
+
return {
|
|
17
|
+
id: "unit",
|
|
18
|
+
name: "UNIT",
|
|
19
|
+
type: DashboardVariableType.ProjectLabel,
|
|
20
|
+
labelOptions: [
|
|
21
|
+
{ label: "0660", value: UNIT_660 },
|
|
22
|
+
{ label: "0661", value: UNIT_661 },
|
|
23
|
+
],
|
|
24
|
+
...overrides,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function filter(
|
|
29
|
+
overrides: Partial<DashboardVariable> = {},
|
|
30
|
+
labelIds?: Array<string>,
|
|
31
|
+
): ReturnType<typeof DashboardLabelVariable.getFilter> {
|
|
32
|
+
return DashboardLabelVariable.getFilter({
|
|
33
|
+
labelVariableId: "unit",
|
|
34
|
+
labelIds,
|
|
35
|
+
variables: [variable(overrides)],
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe("project label dashboard variable filters", () => {
|
|
40
|
+
test("keeps existing widgets with fixed labels unchanged", () => {
|
|
41
|
+
expect(DashboardLabelVariable.getFilter({ labelIds: [NETWORK] })).toEqual(
|
|
42
|
+
new Includes([NETWORK]),
|
|
43
|
+
);
|
|
44
|
+
expect(DashboardLabelVariable.getFilter({})).toBeUndefined();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("a title or an unbound variable does not change the query", () => {
|
|
48
|
+
expect(
|
|
49
|
+
DashboardLabelVariable.getFilter({
|
|
50
|
+
variables: [variable({ selectedValue: UNIT_660 })],
|
|
51
|
+
}),
|
|
52
|
+
).toBeUndefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test.each([UNIT_660, UNIT_661])(
|
|
56
|
+
"filters by selected label ID %s",
|
|
57
|
+
(id: string) => {
|
|
58
|
+
expect(filter({ selectedValue: id })).toEqual(new Includes([id]));
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
test("uses an absent selection's default", () => {
|
|
63
|
+
expect(filter({ defaultValue: UNIT_660 })).toEqual(
|
|
64
|
+
new Includes([UNIT_660]),
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("All overrides a default and retains the fixed label condition", () => {
|
|
69
|
+
expect(
|
|
70
|
+
filter({ defaultValue: UNIT_660, selectedValue: "" }, [NETWORK]),
|
|
71
|
+
).toEqual(new Includes([NETWORK]));
|
|
72
|
+
expect(filter({ selectedValue: "" })).toBeUndefined();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("multi-select is OR within units and AND with fixed labels", () => {
|
|
76
|
+
expect(
|
|
77
|
+
filter({ isMultiSelect: true, selectedValues: [UNIT_660, UNIT_661] }, [
|
|
78
|
+
NETWORK,
|
|
79
|
+
]),
|
|
80
|
+
).toEqual(new IncludesAnyOfGroups([[NETWORK], [UNIT_660, UNIT_661]]));
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("empty multi-select ignores a stale scalar and default", () => {
|
|
84
|
+
expect(
|
|
85
|
+
filter(
|
|
86
|
+
{
|
|
87
|
+
isMultiSelect: true,
|
|
88
|
+
selectedValues: [],
|
|
89
|
+
selectedValue: UNIT_660,
|
|
90
|
+
defaultValue: UNIT_661,
|
|
91
|
+
},
|
|
92
|
+
[NETWORK],
|
|
93
|
+
),
|
|
94
|
+
).toEqual(new Includes([NETWORK]));
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("does not mutate saved configuration and deduplicates repeated picks", () => {
|
|
98
|
+
const saved: DashboardVariable = variable({
|
|
99
|
+
isMultiSelect: true,
|
|
100
|
+
selectedValues: [UNIT_660, UNIT_660],
|
|
101
|
+
});
|
|
102
|
+
const before: string = JSON.stringify(saved);
|
|
103
|
+
const fixed: Array<string> = [NETWORK, NETWORK];
|
|
104
|
+
expect(
|
|
105
|
+
DashboardLabelVariable.getFilter({
|
|
106
|
+
labelIds: fixed,
|
|
107
|
+
labelVariableId: saved.id,
|
|
108
|
+
variables: [saved],
|
|
109
|
+
}),
|
|
110
|
+
).toEqual(new IncludesAnyOfGroups([[NETWORK], [UNIT_660]]));
|
|
111
|
+
expect(JSON.stringify(saved)).toBe(before);
|
|
112
|
+
expect(fixed).toEqual([NETWORK, NETWORK]);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("binding survives a variable rename and display name changes", () => {
|
|
116
|
+
expect(
|
|
117
|
+
filter({
|
|
118
|
+
name: "BRANCH",
|
|
119
|
+
selectedValue: UNIT_660,
|
|
120
|
+
labelOptions: [{ label: "Renamed unit", value: UNIT_660 }],
|
|
121
|
+
}),
|
|
122
|
+
).toEqual(new Includes([UNIT_660]));
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("missing, duplicate, or incompatible variable definitions are errors", () => {
|
|
126
|
+
for (const variables of [
|
|
127
|
+
[],
|
|
128
|
+
[variable(), variable()],
|
|
129
|
+
[variable({ type: DashboardVariableType.CustomList })],
|
|
130
|
+
]) {
|
|
131
|
+
expect(() => {
|
|
132
|
+
return DashboardLabelVariable.getFilter({
|
|
133
|
+
labelVariableId: "unit",
|
|
134
|
+
variables,
|
|
135
|
+
});
|
|
136
|
+
}).toThrow(/label variable/);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test.each(["0660", NETWORK])(
|
|
141
|
+
"rejects selections not in the configured options: %s",
|
|
142
|
+
(selectedValue: string) => {
|
|
143
|
+
expect(() => {
|
|
144
|
+
return filter({ selectedValue });
|
|
145
|
+
}).toThrow(/offered by this dashboard/);
|
|
146
|
+
},
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
test("an invalid default does not silently fall back to all monitors", () => {
|
|
150
|
+
expect(() => {
|
|
151
|
+
return filter({ defaultValue: NETWORK });
|
|
152
|
+
}).toThrow(/offered by this dashboard/);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("validates every multi-selection instead of dropping invalid values", () => {
|
|
156
|
+
expect(() => {
|
|
157
|
+
return filter({
|
|
158
|
+
isMultiSelect: true,
|
|
159
|
+
selectedValues: [UNIT_660, NETWORK],
|
|
160
|
+
});
|
|
161
|
+
}).toThrow(/offered by this dashboard/);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("bounds multi-selection size", () => {
|
|
165
|
+
expect(() => {
|
|
166
|
+
return filter({
|
|
167
|
+
isMultiSelect: true,
|
|
168
|
+
selectedValues: Array(101).fill(UNIT_660) as Array<string>,
|
|
169
|
+
});
|
|
170
|
+
}).toThrow(/100 labels/);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test.each([
|
|
174
|
+
undefined,
|
|
175
|
+
[],
|
|
176
|
+
[{ label: "0660", value: "0660" }],
|
|
177
|
+
[{ label: "", value: UNIT_660 }],
|
|
178
|
+
[{ label: " ", value: UNIT_660 }],
|
|
179
|
+
[{ label: "x".repeat(1025), value: UNIT_660 }],
|
|
180
|
+
[
|
|
181
|
+
{ label: "0660", value: UNIT_660 },
|
|
182
|
+
{ label: "Duplicate", value: UNIT_660 },
|
|
183
|
+
],
|
|
184
|
+
Array(1001).fill({ label: "0660", value: UNIT_660 }),
|
|
185
|
+
])(
|
|
186
|
+
"rejects malformed label choices %#",
|
|
187
|
+
(labelOptions: DashboardVariable["labelOptions"]) => {
|
|
188
|
+
expect(() => {
|
|
189
|
+
return filter({ labelOptions });
|
|
190
|
+
}).toThrow();
|
|
191
|
+
},
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
test("filter operators survive the API serialization round trip", () => {
|
|
195
|
+
const original: IncludesAnyOfGroups = filter({ selectedValue: UNIT_660 }, [
|
|
196
|
+
NETWORK,
|
|
197
|
+
]) as IncludesAnyOfGroups;
|
|
198
|
+
expect(
|
|
199
|
+
JSONFunctions.deserializeValue(JSONFunctions.serializeValue(original)),
|
|
200
|
+
).toEqual(original);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
describe("dashboard title display interpolation", () => {
|
|
205
|
+
test.each([
|
|
206
|
+
[{ selectedValue: UNIT_660 }, "0660 NETWORK"],
|
|
207
|
+
[{ defaultValue: UNIT_661 }, "0661 NETWORK"],
|
|
208
|
+
[{ selectedValue: "", defaultValue: UNIT_660 }, "All NETWORK"],
|
|
209
|
+
[
|
|
210
|
+
{ isMultiSelect: true, selectedValues: [UNIT_660, UNIT_661] },
|
|
211
|
+
"0660, 0661 NETWORK",
|
|
212
|
+
],
|
|
213
|
+
[
|
|
214
|
+
{ isMultiSelect: true, selectedValues: [], defaultValue: UNIT_660 },
|
|
215
|
+
"All NETWORK",
|
|
216
|
+
],
|
|
217
|
+
[{ selectedValue: NETWORK }, "Unavailable label NETWORK"],
|
|
218
|
+
])(
|
|
219
|
+
"renders a label selection using display names %#",
|
|
220
|
+
(overrides: Partial<DashboardVariable>, expected: string) => {
|
|
221
|
+
expect(
|
|
222
|
+
DashboardLabelVariable.interpolateTitle("{{UNIT}} NETWORK", [
|
|
223
|
+
variable(overrides),
|
|
224
|
+
]),
|
|
225
|
+
).toBe(expected);
|
|
226
|
+
},
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
test("preserves unknown references and ordinary titles", () => {
|
|
230
|
+
expect(
|
|
231
|
+
DashboardLabelVariable.interpolateTitle("{{missing}} NETWORK", [
|
|
232
|
+
variable(),
|
|
233
|
+
]),
|
|
234
|
+
).toBe("{{missing}} NETWORK");
|
|
235
|
+
expect(DashboardLabelVariable.interpolateTitle("Monitors", [])).toBe(
|
|
236
|
+
"Monitors",
|
|
237
|
+
);
|
|
238
|
+
expect(
|
|
239
|
+
DashboardLabelVariable.interpolateTitle(undefined, []),
|
|
240
|
+
).toBeUndefined();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test("supports multiple references and text values without interpreting markup", () => {
|
|
244
|
+
const text: DashboardVariable = {
|
|
245
|
+
id: "env",
|
|
246
|
+
name: "ENV",
|
|
247
|
+
type: DashboardVariableType.TextInput,
|
|
248
|
+
selectedValue: "<b>prod</b>",
|
|
249
|
+
};
|
|
250
|
+
expect(
|
|
251
|
+
DashboardLabelVariable.interpolateTitle("{{UNIT}} / {{ENV}} / {{UNIT}}", [
|
|
252
|
+
variable({ selectedValue: UNIT_660 }),
|
|
253
|
+
text,
|
|
254
|
+
]),
|
|
255
|
+
).toBe("0660 / <b>prod</b> / 0660");
|
|
256
|
+
});
|
|
257
|
+
});
|
|
@@ -100,7 +100,10 @@ describe("DashboardVariableUrlState", () => {
|
|
|
100
100
|
});
|
|
101
101
|
|
|
102
102
|
test("applies multi-selected values from the url", () => {
|
|
103
|
-
const variable: DashboardVariable = makeVariable({
|
|
103
|
+
const variable: DashboardVariable = makeVariable({
|
|
104
|
+
name: "region",
|
|
105
|
+
isMultiSelect: true,
|
|
106
|
+
});
|
|
104
107
|
const result: Array<DashboardVariable> =
|
|
105
108
|
DashboardVariableUrlState.applyUrlToVariables([variable], {
|
|
106
109
|
region: { selectedValues: ["a", "b"] },
|
|
@@ -108,6 +111,55 @@ describe("DashboardVariableUrlState", () => {
|
|
|
108
111
|
expect(result[0]?.selectedValues).toEqual(["a", "b"]);
|
|
109
112
|
});
|
|
110
113
|
|
|
114
|
+
test("restores one choice into a multi-select and clears a stale scalar", () => {
|
|
115
|
+
const variable: DashboardVariable = makeVariable({
|
|
116
|
+
name: "UNIT",
|
|
117
|
+
type: DashboardVariableType.ProjectLabel,
|
|
118
|
+
isMultiSelect: true,
|
|
119
|
+
selectedValue: "old",
|
|
120
|
+
selectedValues: ["old"],
|
|
121
|
+
});
|
|
122
|
+
const result: Array<DashboardVariable> =
|
|
123
|
+
DashboardVariableUrlState.applyUrlToVariables([variable], {
|
|
124
|
+
UNIT: { selectedValue: "label-0660" },
|
|
125
|
+
});
|
|
126
|
+
expect(result[0]?.selectedValues).toEqual(["label-0660"]);
|
|
127
|
+
expect(result[0]?.selectedValue).toBeUndefined();
|
|
128
|
+
expect(variable.selectedValues).toEqual(["old"]);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("normalizes an explicit All to an empty multi-select", () => {
|
|
132
|
+
const result: Array<DashboardVariable> =
|
|
133
|
+
DashboardVariableUrlState.applyUrlToVariables(
|
|
134
|
+
[
|
|
135
|
+
makeVariable({
|
|
136
|
+
name: "UNIT",
|
|
137
|
+
isMultiSelect: true,
|
|
138
|
+
selectedValues: ["old"],
|
|
139
|
+
}),
|
|
140
|
+
],
|
|
141
|
+
{ UNIT: { selectedValue: "" } },
|
|
142
|
+
);
|
|
143
|
+
expect(result[0]?.selectedValues).toEqual([]);
|
|
144
|
+
expect(result[0]?.selectedValue).toBeUndefined();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("normalizes a comma-containing scalar using the single-select definition", () => {
|
|
148
|
+
const result: Array<DashboardVariable> =
|
|
149
|
+
DashboardVariableUrlState.applyUrlToVariables(
|
|
150
|
+
[
|
|
151
|
+
makeVariable({
|
|
152
|
+
name: "text",
|
|
153
|
+
type: DashboardVariableType.TextInput,
|
|
154
|
+
selectedValues: ["stale"],
|
|
155
|
+
}),
|
|
156
|
+
],
|
|
157
|
+
DashboardVariableUrlState.parseFromSearch("?var-text=a,b"),
|
|
158
|
+
);
|
|
159
|
+
expect(result[0]?.selectedValue).toBe("a,b");
|
|
160
|
+
expect(result[0]?.selectedValues).toBeUndefined();
|
|
161
|
+
});
|
|
162
|
+
|
|
111
163
|
test("does not mutate the original variable object", () => {
|
|
112
164
|
const variable: DashboardVariable = makeVariable({
|
|
113
165
|
name: "cluster",
|
|
@@ -135,7 +187,7 @@ describe("DashboardVariableUrlState", () => {
|
|
|
135
187
|
test("a shared url reproduces the selection on the variables", () => {
|
|
136
188
|
const variables: Array<DashboardVariable> = [
|
|
137
189
|
makeVariable({ name: "cluster" }),
|
|
138
|
-
makeVariable({ name: "region" }),
|
|
190
|
+
makeVariable({ name: "region", isMultiSelect: true }),
|
|
139
191
|
];
|
|
140
192
|
|
|
141
193
|
const fromUrl: Record<string, VariableUrlSnapshot> =
|
|
@@ -149,14 +201,7 @@ describe("DashboardVariableUrlState", () => {
|
|
|
149
201
|
expect(applied[1]?.selectedValues).toEqual(["us", "eu"]);
|
|
150
202
|
});
|
|
151
203
|
|
|
152
|
-
|
|
153
|
-
* "All" is the absence of a var- param — writeToBrowserUrl emits
|
|
154
|
-
* nothing for an empty selection, so a reload cannot tell "cleared"
|
|
155
|
-
* from "never touched" and must treat both as All. That only holds
|
|
156
|
-
* because resolveValue ignores defaultValue for a multi-select; if it
|
|
157
|
-
* fell back, a viewer who cleared the popover would silently get the
|
|
158
|
-
* author's Default back on every refresh and on every shared link.
|
|
159
|
-
*/
|
|
204
|
+
// Explicit All must override any selection persisted in the saved config.
|
|
160
205
|
test("a cleared multi-select survives a url round trip as All", () => {
|
|
161
206
|
window.history.replaceState({}, "", "/dashboard");
|
|
162
207
|
DashboardVariableUrlState.writeToBrowserUrl([
|
|
@@ -168,7 +213,7 @@ describe("DashboardVariableUrlState", () => {
|
|
|
168
213
|
}),
|
|
169
214
|
]);
|
|
170
215
|
|
|
171
|
-
expect(window.location.search).toBe("");
|
|
216
|
+
expect(window.location.search).toBe("?var-region=");
|
|
172
217
|
|
|
173
218
|
const applied: Array<DashboardVariable> =
|
|
174
219
|
DashboardVariableUrlState.applyUrlToVariables(
|
|
@@ -177,18 +222,60 @@ describe("DashboardVariableUrlState", () => {
|
|
|
177
222
|
name: "region",
|
|
178
223
|
isMultiSelect: true,
|
|
179
224
|
defaultValue: "us",
|
|
225
|
+
selectedValues: ["eu"],
|
|
180
226
|
}),
|
|
181
227
|
],
|
|
182
228
|
DashboardVariableUrlState.parseFromSearch(window.location.search),
|
|
183
229
|
);
|
|
184
230
|
|
|
185
|
-
expect(applied[0]?.selectedValues).
|
|
231
|
+
expect(applied[0]?.selectedValues).toEqual([]);
|
|
186
232
|
expect(
|
|
187
233
|
DashboardVariableInterpolation.resolveValue(
|
|
188
234
|
applied[0] as DashboardVariable,
|
|
189
235
|
),
|
|
190
236
|
).toBeUndefined();
|
|
191
237
|
});
|
|
238
|
+
|
|
239
|
+
test("a single project label selection survives a multi-select URL round trip", () => {
|
|
240
|
+
window.history.replaceState({}, "", "/dashboard");
|
|
241
|
+
const variable: DashboardVariable = makeVariable({
|
|
242
|
+
name: "UNIT",
|
|
243
|
+
type: DashboardVariableType.ProjectLabel,
|
|
244
|
+
isMultiSelect: true,
|
|
245
|
+
selectedValues: ["0660"],
|
|
246
|
+
});
|
|
247
|
+
DashboardVariableUrlState.writeToBrowserUrl([variable]);
|
|
248
|
+
expect(window.location.search).toBe("?var-UNIT=0660");
|
|
249
|
+
const [restored]: Array<DashboardVariable> =
|
|
250
|
+
DashboardVariableUrlState.applyUrlToVariables(
|
|
251
|
+
[{ ...variable, selectedValues: undefined }],
|
|
252
|
+
DashboardVariableUrlState.parseFromSearch(window.location.search),
|
|
253
|
+
);
|
|
254
|
+
expect(DashboardVariableInterpolation.resolveValue(restored!)).toEqual({
|
|
255
|
+
multi: ["0660"],
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test("explicit All survives a single-select URL round trip despite a stored default", () => {
|
|
260
|
+
window.history.replaceState({}, "", "/dashboard");
|
|
261
|
+
const variable: DashboardVariable = makeVariable({
|
|
262
|
+
name: "UNIT",
|
|
263
|
+
type: DashboardVariableType.ProjectLabel,
|
|
264
|
+
defaultValue: "0660",
|
|
265
|
+
selectedValue: "",
|
|
266
|
+
});
|
|
267
|
+
DashboardVariableUrlState.writeToBrowserUrl([variable]);
|
|
268
|
+
expect(window.location.search).toBe("?var-UNIT=");
|
|
269
|
+
const [restored]: Array<DashboardVariable> =
|
|
270
|
+
DashboardVariableUrlState.applyUrlToVariables(
|
|
271
|
+
[{ ...variable, selectedValue: undefined }],
|
|
272
|
+
DashboardVariableUrlState.parseFromSearch(window.location.search),
|
|
273
|
+
);
|
|
274
|
+
expect(restored?.selectedValue).toBe("");
|
|
275
|
+
expect(
|
|
276
|
+
DashboardVariableInterpolation.resolveValue(restored!),
|
|
277
|
+
).toBeUndefined();
|
|
278
|
+
});
|
|
192
279
|
});
|
|
193
280
|
|
|
194
281
|
describe("writeToBrowserUrl", () => {
|
|
@@ -209,7 +296,11 @@ describe("DashboardVariableUrlState", () => {
|
|
|
209
296
|
|
|
210
297
|
test("writes multi-selected values joined by commas", () => {
|
|
211
298
|
DashboardVariableUrlState.writeToBrowserUrl([
|
|
212
|
-
makeVariable({
|
|
299
|
+
makeVariable({
|
|
300
|
+
name: "region",
|
|
301
|
+
isMultiSelect: true,
|
|
302
|
+
selectedValues: ["us", "eu"],
|
|
303
|
+
}),
|
|
213
304
|
]);
|
|
214
305
|
expect(
|
|
215
306
|
DashboardVariableUrlState.parseFromSearch(window.location.search)[
|
|
@@ -239,6 +330,41 @@ describe("DashboardVariableUrlState", () => {
|
|
|
239
330
|
expect(window.location.search).toBe("");
|
|
240
331
|
});
|
|
241
332
|
|
|
333
|
+
test("keeps explicit All distinct from an untouched default", () => {
|
|
334
|
+
DashboardVariableUrlState.writeToBrowserUrl([
|
|
335
|
+
makeVariable({
|
|
336
|
+
name: "cleared",
|
|
337
|
+
selectedValue: "",
|
|
338
|
+
defaultValue: "prod",
|
|
339
|
+
}),
|
|
340
|
+
makeVariable({ name: "untouched", defaultValue: "prod" }),
|
|
341
|
+
makeVariable({
|
|
342
|
+
name: "clearedMulti",
|
|
343
|
+
isMultiSelect: true,
|
|
344
|
+
selectedValues: [],
|
|
345
|
+
}),
|
|
346
|
+
makeVariable({ name: "untouchedMulti", isMultiSelect: true }),
|
|
347
|
+
]);
|
|
348
|
+
expect(window.location.search).toBe("?var-cleared=&var-clearedMulti=");
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
test("writes only the selection field used by the saved selection mode", () => {
|
|
352
|
+
DashboardVariableUrlState.writeToBrowserUrl([
|
|
353
|
+
makeVariable({
|
|
354
|
+
name: "single",
|
|
355
|
+
selectedValue: "prod",
|
|
356
|
+
selectedValues: ["stale"],
|
|
357
|
+
}),
|
|
358
|
+
makeVariable({
|
|
359
|
+
name: "multi",
|
|
360
|
+
isMultiSelect: true,
|
|
361
|
+
selectedValue: "stale",
|
|
362
|
+
selectedValues: [],
|
|
363
|
+
}),
|
|
364
|
+
]);
|
|
365
|
+
expect(window.location.search).toBe("?var-single=prod&var-multi=");
|
|
366
|
+
});
|
|
367
|
+
|
|
242
368
|
test("does not push a new history entry (uses replaceState)", () => {
|
|
243
369
|
const lengthBefore: number = window.history.length;
|
|
244
370
|
DashboardVariableUrlState.writeToBrowserUrl([
|
|
@@ -250,7 +376,11 @@ describe("DashboardVariableUrlState", () => {
|
|
|
250
376
|
test("write -> parse round trip preserves the selection", () => {
|
|
251
377
|
DashboardVariableUrlState.writeToBrowserUrl([
|
|
252
378
|
makeVariable({ name: "cluster", selectedValue: "prod" }),
|
|
253
|
-
makeVariable({
|
|
379
|
+
makeVariable({
|
|
380
|
+
name: "region",
|
|
381
|
+
isMultiSelect: true,
|
|
382
|
+
selectedValues: ["us", "eu"],
|
|
383
|
+
}),
|
|
254
384
|
]);
|
|
255
385
|
const parsed: Record<string, VariableUrlSnapshot> =
|
|
256
386
|
DashboardVariableUrlState.parseFromSearch(window.location.search);
|
|
@@ -235,6 +235,87 @@ describe("MetricUnitUtil", () => {
|
|
|
235
235
|
});
|
|
236
236
|
});
|
|
237
237
|
|
|
238
|
+
describe("getFamilyBaseUnit", () => {
|
|
239
|
+
test("returns the family's canonical base for every member", () => {
|
|
240
|
+
for (const unit of [
|
|
241
|
+
"B",
|
|
242
|
+
"b",
|
|
243
|
+
"By",
|
|
244
|
+
"bytes",
|
|
245
|
+
"KB",
|
|
246
|
+
"kby",
|
|
247
|
+
"MB",
|
|
248
|
+
"GB",
|
|
249
|
+
"TB",
|
|
250
|
+
"PB",
|
|
251
|
+
]) {
|
|
252
|
+
expect(MetricUnitUtil.getFamilyBaseUnit(unit)).toBe("B");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
for (const unit of [
|
|
256
|
+
"ns",
|
|
257
|
+
"µs",
|
|
258
|
+
"us",
|
|
259
|
+
"ms",
|
|
260
|
+
"s",
|
|
261
|
+
"sec",
|
|
262
|
+
"seconds",
|
|
263
|
+
"min",
|
|
264
|
+
"hours",
|
|
265
|
+
"d",
|
|
266
|
+
"days",
|
|
267
|
+
]) {
|
|
268
|
+
expect(MetricUnitUtil.getFamilyBaseUnit(unit)).toBe("sec");
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
for (const unit of ["%", "percent", "1"]) {
|
|
272
|
+
expect(MetricUnitUtil.getFamilyBaseUnit(unit)).toBe("%");
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
for (const unit of ["bit", "bits", "kbit", "mbit", "gbit"]) {
|
|
276
|
+
expect(MetricUnitUtil.getFamilyBaseUnit(unit)).toBe("bit");
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
test("is case- and whitespace-insensitive", () => {
|
|
281
|
+
expect(MetricUnitUtil.getFamilyBaseUnit(" GB ")).toBe("B");
|
|
282
|
+
expect(MetricUnitUtil.getFamilyBaseUnit("MS")).toBe("sec");
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test("returns null for an unknown or empty unit", () => {
|
|
286
|
+
expect(MetricUnitUtil.getFamilyBaseUnit(undefined)).toBeNull();
|
|
287
|
+
expect(MetricUnitUtil.getFamilyBaseUnit("")).toBeNull();
|
|
288
|
+
expect(MetricUnitUtil.getFamilyBaseUnit(" ")).toBeNull();
|
|
289
|
+
expect(MetricUnitUtil.getFamilyBaseUnit("cores")).toBeNull();
|
|
290
|
+
expect(MetricUnitUtil.getFamilyBaseUnit("widgets")).toBeNull();
|
|
291
|
+
// Binary prefixes are deliberately not in any family here.
|
|
292
|
+
expect(MetricUnitUtil.getFamilyBaseUnit("KiBy")).toBeNull();
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
/*
|
|
296
|
+
* The base is the unit every other member converts into with the
|
|
297
|
+
* family's own converter — this is the contract MetricValueFormatter
|
|
298
|
+
* relies on when it restates "2500 GB" as bytes before scaling.
|
|
299
|
+
*/
|
|
300
|
+
test("the base it names round-trips through convertToMetricUnit", () => {
|
|
301
|
+
expect(
|
|
302
|
+
MetricUnitUtil.convertToMetricUnit({
|
|
303
|
+
value: 2500,
|
|
304
|
+
fromUnit: "GB",
|
|
305
|
+
metricUnit: MetricUnitUtil.getFamilyBaseUnit("GB") as string,
|
|
306
|
+
}),
|
|
307
|
+
).toBe(2.5e12);
|
|
308
|
+
|
|
309
|
+
expect(
|
|
310
|
+
MetricUnitUtil.convertToMetricUnit({
|
|
311
|
+
value: 36,
|
|
312
|
+
fromUnit: "hours",
|
|
313
|
+
metricUnit: MetricUnitUtil.getFamilyBaseUnit("hours") as string,
|
|
314
|
+
}),
|
|
315
|
+
).toBe(129600);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
238
319
|
describe("hasCompatibleUnitFamily", () => {
|
|
239
320
|
test("true for known families", () => {
|
|
240
321
|
expect(MetricUnitUtil.hasCompatibleUnitFamily("bytes")).toBe(true);
|