@oneuptime/common 14.0.0 → 14.0.1
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/Index.ts +4 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +2 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.ts +522 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +38 -4
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.ts +603 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.ts +248 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/DatabaseService.ts +10 -0
- package/Server/Services/Index.ts +4 -0
- package/Server/Services/MonitorService.ts +3 -2
- package/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.ts +385 -0
- package/Server/Services/ServiceLevelObjectiveLabelRuleService.ts +51 -0
- package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +92 -16
- package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +36 -1
- package/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.ts +521 -0
- package/Server/Services/ServiceLevelObjectiveOwnerRuleService.ts +51 -0
- package/Server/Services/ServiceLevelObjectiveService.ts +28 -0
- package/Server/Types/Workflow/Components/Telegram/SendMessageToChat.ts +27 -1
- package/Server/Utils/AI/Toolbox/SloTools.ts +1 -0
- package/Server/Utils/Monitor/AffectedResourceList.ts +31 -73
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +1 -1
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +1 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +181 -136
- package/Server/Utils/Monitor/RootCauseList.ts +139 -0
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +28 -0
- package/Server/Utils/Slo/SloRulePatternValidator.ts +42 -0
- package/Tests/App/Dashboard/FeedFilterSortIntegration.test.tsx +1632 -0
- package/Tests/App/Dashboard/FeedOptionsLocales.test.ts +250 -0
- package/Tests/App/Dashboard/FeedOrdering.test.ts +279 -9
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +60 -1
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +594 -3
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +646 -0
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +612 -2
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +30 -0
- package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +1202 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +52 -1
- package/Tests/App/Dashboard/SloFeed.test.tsx +106 -1
- package/Tests/App/Dashboard/SloMonitorRuleCriteria.test.tsx +566 -0
- package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +6 -4
- package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +186 -0
- package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +388 -44
- package/Tests/App/Dashboard/SloOverviewLayout.test.tsx +613 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +0 -8
- package/Tests/Models/DatabaseModels/SloLabelAndOwnerRuleModels.test.ts +404 -0
- package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +17 -1
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddSloLabelAndOwnerRulesMigration.test.ts +407 -0
- package/Tests/Server/Infrastructure/Postgres/AddSloMonitorRuleMonitorTypeMigration.test.ts +171 -0
- package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +88 -4
- package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +104 -0
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +48 -1
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -0
- package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +1170 -0
- package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleServices.test.ts +172 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +323 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +115 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleTriggers.test.ts +21 -2
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorTypePostgres.test.ts +480 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +162 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +45 -6
- package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +745 -0
- package/Tests/Server/Types/Markdown.test.ts +2 -1
- package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +49 -0
- package/Tests/Server/Types/Workflow/Components/TelegramSendMessageToChat.test.ts +331 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +10 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +1 -1
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +405 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +1101 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +106 -80
- package/Tests/Server/Utils/Monitor/RootCauseList.test.ts +252 -0
- package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +154 -0
- package/Tests/Server/Utils/SSRFProtection.test.ts +111 -0
- package/Tests/Server/Utils/Slo/SloRulePatternValidator.test.ts +67 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +213 -0
- package/Tests/Types/API/Route.test.ts +56 -0
- package/Tests/Types/API/URLSchemeLikePath.test.ts +304 -0
- package/Tests/UI/Components/FeedOptions.test.ts +1404 -0
- package/Tests/UI/Components/FeedOptionsButton.test.tsx +2603 -0
- package/Tests/UI/Components/Icon.test.tsx +26 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/useFeedItemsViewKey.test.tsx +1017 -0
- package/Tests/UI/Components/useFeedOptions.test.tsx +1107 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +102 -0
- package/Tests/Utils/Slo/SloDuration.test.ts +115 -24
- package/Tests/Utils/Slo/SloHealth.test.ts +93 -10
- package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +109 -0
- package/Tests/Utils/Slo/SloOverviewText.test.ts +64 -0
- package/Types/API/Route.ts +19 -2
- package/Types/API/URL.ts +26 -2
- package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +6 -5
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +9 -0
- package/Types/Permission.ts +90 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +11 -0
- package/Types/Rules/RuleRun.ts +4 -0
- package/UI/Components/Feed/FeedOptions.ts +427 -0
- package/UI/Components/Feed/FeedOptionsButton.tsx +692 -0
- package/UI/Components/Feed/useFeedItems.ts +28 -9
- package/UI/Components/Feed/useFeedOptions.ts +225 -0
- package/UI/Components/Icon/Icon.tsx +1 -1
- package/Utils/LabelRuleImportExport.ts +27 -9
- package/Utils/Monitor/MetricValueFormatter.ts +2 -2
- package/Utils/Rules/MonitorTypeRuleCriteria.ts +31 -0
- package/Utils/Slo/SloDuration.ts +22 -6
- package/Utils/Slo/SloHealth.ts +8 -7
- package/Utils/Slo/SloMonitorRuleCriteria.ts +33 -1
- package/Utils/Slo/SloOverviewText.ts +33 -0
- package/Utils/Slo/SloProjection.ts +4 -3
- package/build/dist/Models/DatabaseModels/Index.js +4 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +2 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js +530 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +39 -4
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js +612 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js +93 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +7 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +4 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +3 -2
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js +295 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js +56 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +59 -14
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +22 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js +400 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js +56 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +21 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js +20 -1
- package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +22 -51
- package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +139 -109
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/RootCauseList.js +101 -0
- package/build/dist/Server/Utils/Monitor/RootCauseList.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +28 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js +28 -0
- package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js.map +1 -0
- package/build/dist/Types/API/Route.js +18 -2
- package/build/dist/Types/API/Route.js.map +1 -1
- package/build/dist/Types/API/URL.js +23 -2
- package/build/dist/Types/API/URL.js.map +1 -1
- package/build/dist/Types/Permission.js +84 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +11 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedOptions.js +235 -0
- package/build/dist/UI/Components/Feed/FeedOptions.js.map +1 -0
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js +346 -0
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -0
- package/build/dist/UI/Components/Feed/useFeedItems.js +17 -7
- package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -1
- package/build/dist/UI/Components/Feed/useFeedOptions.js +130 -0
- package/build/dist/UI/Components/Feed/useFeedOptions.js.map +1 -0
- package/build/dist/UI/Components/Icon/Icon.js +1 -1
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/Utils/LabelRuleImportExport.js +22 -6
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/Monitor/MetricValueFormatter.js +2 -2
- package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js +18 -0
- package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js.map +1 -0
- package/build/dist/Utils/Slo/SloDuration.js +13 -5
- package/build/dist/Utils/Slo/SloDuration.js.map +1 -1
- package/build/dist/Utils/Slo/SloHealth.js +8 -7
- package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +16 -1
- package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -1
- package/build/dist/Utils/Slo/SloOverviewText.js +16 -0
- package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -1
- package/build/dist/Utils/Slo/SloProjection.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
import {
|
|
2
|
+
afterEach,
|
|
3
|
+
beforeEach,
|
|
4
|
+
describe,
|
|
5
|
+
expect,
|
|
6
|
+
jest,
|
|
7
|
+
test,
|
|
8
|
+
} from "@jest/globals";
|
|
9
|
+
import {
|
|
10
|
+
cleanup,
|
|
11
|
+
render,
|
|
12
|
+
screen,
|
|
13
|
+
waitFor,
|
|
14
|
+
within,
|
|
15
|
+
} from "@testing-library/react";
|
|
16
|
+
import userEvent from "@testing-library/user-event";
|
|
17
|
+
import React from "react";
|
|
18
|
+
import getSloMonitorRuleFormFields from "../../../../App/FeatureSet/Dashboard/src/Pages/Slo/View/SloMonitorRuleFormFields";
|
|
19
|
+
import ServiceLevelObjectiveMonitorRule from "../../../Models/DatabaseModels/ServiceLevelObjectiveMonitorRule";
|
|
20
|
+
import FilterCondition from "../../../Types/Filter/FilterCondition";
|
|
21
|
+
import MonitorType from "../../../Types/Monitor/MonitorType";
|
|
22
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
23
|
+
import Permission from "../../../Types/Permission";
|
|
24
|
+
import RuleCriteria, {
|
|
25
|
+
RULE_CRITERIA_LEGACY_NEVER_MATCH_PATTERN,
|
|
26
|
+
RULE_CRITERIA_SCHEMA_VERSION,
|
|
27
|
+
RuleCriteriaOperator,
|
|
28
|
+
} from "../../../Types/Rules/RuleCriteria";
|
|
29
|
+
import ModelForm, { FormType } from "../../../UI/Components/Forms/ModelForm";
|
|
30
|
+
import { getLegacyRuleCriteriaFields } from "../../../UI/Components/RuleCriteria/RuleCriteriaModelForm";
|
|
31
|
+
import { getRuleCriteriaSummaryText } from "../../../UI/Components/RuleCriteria/RuleCriteriaSummary";
|
|
32
|
+
|
|
33
|
+
/*
|
|
34
|
+
* Drive the real ModelForm and dropdowns using the SLO page's actual fields.
|
|
35
|
+
* This catches fields being removed by column permissions, builder conversion,
|
|
36
|
+
* edit loading, and serialization, not just the labels in the configuration.
|
|
37
|
+
*/
|
|
38
|
+
let savedRule: ServiceLevelObjectiveMonitorRule | null = null;
|
|
39
|
+
let submittedRule: ServiceLevelObjectiveMonitorRule | null = null;
|
|
40
|
+
let selectedFields: Record<string, unknown> = {};
|
|
41
|
+
let permissions: Array<Permission> = [];
|
|
42
|
+
|
|
43
|
+
jest.mock("../../../UI/Utils/Permission", () => {
|
|
44
|
+
return {
|
|
45
|
+
__esModule: true,
|
|
46
|
+
default: {
|
|
47
|
+
getAllPermissions: (): Array<Permission> => {
|
|
48
|
+
return permissions;
|
|
49
|
+
},
|
|
50
|
+
getProjectPermissions: (): null => {
|
|
51
|
+
return null;
|
|
52
|
+
},
|
|
53
|
+
getGlobalPermissions: (): { globalPermissions: Array<Permission> } => {
|
|
54
|
+
return { globalPermissions: permissions };
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
jest.mock("../../../UI/Utils/User", () => {
|
|
61
|
+
return {
|
|
62
|
+
__esModule: true,
|
|
63
|
+
default: {
|
|
64
|
+
isMasterAdmin: (): boolean => {
|
|
65
|
+
return false;
|
|
66
|
+
},
|
|
67
|
+
getUserId: (): null => {
|
|
68
|
+
return null;
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
jest.mock("../../../UI/Utils/Translation", () => {
|
|
75
|
+
return {
|
|
76
|
+
__esModule: true,
|
|
77
|
+
default: () => {
|
|
78
|
+
return {
|
|
79
|
+
translateString: (value: string | undefined): string | undefined => {
|
|
80
|
+
return value;
|
|
81
|
+
},
|
|
82
|
+
translateValue: (value: unknown): unknown => {
|
|
83
|
+
return value;
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
|
|
91
|
+
return {
|
|
92
|
+
__esModule: true,
|
|
93
|
+
default: {
|
|
94
|
+
getItem: async (data: {
|
|
95
|
+
select: Record<string, unknown>;
|
|
96
|
+
}): Promise<ServiceLevelObjectiveMonitorRule | null> => {
|
|
97
|
+
selectedFields = data.select;
|
|
98
|
+
return savedRule;
|
|
99
|
+
},
|
|
100
|
+
getList: async (): Promise<{
|
|
101
|
+
data: Array<unknown>;
|
|
102
|
+
count: number;
|
|
103
|
+
skip: number;
|
|
104
|
+
limit: number;
|
|
105
|
+
}> => {
|
|
106
|
+
return { data: [], count: 0, skip: 0, limit: 50 };
|
|
107
|
+
},
|
|
108
|
+
getCommonHeaders: (): Record<string, string> => {
|
|
109
|
+
return {};
|
|
110
|
+
},
|
|
111
|
+
createOrUpdate: async (data: {
|
|
112
|
+
model: ServiceLevelObjectiveMonitorRule;
|
|
113
|
+
}): Promise<{ data: ServiceLevelObjectiveMonitorRule }> => {
|
|
114
|
+
submittedRule = data.model;
|
|
115
|
+
return { data: data.model };
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const RULE_ID: string = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa";
|
|
122
|
+
|
|
123
|
+
function criteriaWith(
|
|
124
|
+
field: string,
|
|
125
|
+
operator: RuleCriteriaOperator,
|
|
126
|
+
value: string,
|
|
127
|
+
): RuleCriteria {
|
|
128
|
+
return {
|
|
129
|
+
schemaVersion: RULE_CRITERIA_SCHEMA_VERSION,
|
|
130
|
+
filterCondition: FilterCondition.All,
|
|
131
|
+
filters: [{ field: field, operator: operator, value: value }],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function existingRule(
|
|
136
|
+
criteria?: RuleCriteria,
|
|
137
|
+
): ServiceLevelObjectiveMonitorRule {
|
|
138
|
+
const rule: ServiceLevelObjectiveMonitorRule =
|
|
139
|
+
new ServiceLevelObjectiveMonitorRule();
|
|
140
|
+
rule._id = RULE_ID;
|
|
141
|
+
rule.name = "Production API monitors";
|
|
142
|
+
rule.isEnabled = true;
|
|
143
|
+
if (criteria !== undefined) {
|
|
144
|
+
rule.criteria = criteria;
|
|
145
|
+
}
|
|
146
|
+
return rule;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function renderForm(formType: FormType = FormType.Create): Promise<void> {
|
|
150
|
+
render(
|
|
151
|
+
<ModelForm<ServiceLevelObjectiveMonitorRule>
|
|
152
|
+
modelType={ServiceLevelObjectiveMonitorRule}
|
|
153
|
+
id="slo-monitor-rule-form"
|
|
154
|
+
name="SLO Monitor Rule"
|
|
155
|
+
fields={getSloMonitorRuleFormFields()}
|
|
156
|
+
formType={formType}
|
|
157
|
+
modelIdToEdit={
|
|
158
|
+
formType === FormType.Update ? new ObjectID(RULE_ID) : undefined
|
|
159
|
+
}
|
|
160
|
+
initialValues={
|
|
161
|
+
formType === FormType.Create
|
|
162
|
+
? { name: "Production API monitors", isEnabled: true }
|
|
163
|
+
: undefined
|
|
164
|
+
}
|
|
165
|
+
steps={[
|
|
166
|
+
{ title: "Basic Info", id: "basic-info" },
|
|
167
|
+
{ title: "Match Criteria", id: "match-criteria" },
|
|
168
|
+
]}
|
|
169
|
+
submitButtonText="Save SLO Monitor Rule"
|
|
170
|
+
/>,
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
174
|
+
await user.click(await screen.findByRole("button", { name: /Next/i }));
|
|
175
|
+
await screen.findByTestId("rule-criteria-builder");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async function selectOption(name: string, label: string): Promise<void> {
|
|
179
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
180
|
+
await user.click(screen.getByRole("combobox", { name: name }));
|
|
181
|
+
const options: Array<HTMLElement> = await screen.findAllByText(label, {
|
|
182
|
+
exact: true,
|
|
183
|
+
});
|
|
184
|
+
await user.click(options[options.length - 1]!);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function addCondition(title: string): Promise<void> {
|
|
188
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
189
|
+
await user.click(screen.getByTestId("rule-criteria-add"));
|
|
190
|
+
const index: number = screen.getAllByText("Criteria", { exact: true }).length;
|
|
191
|
+
await selectOption(`Criteria for condition ${index}`, title);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async function submitForm(): Promise<ServiceLevelObjectiveMonitorRule> {
|
|
195
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
196
|
+
await user.click(
|
|
197
|
+
screen.getByRole("button", { name: "Save SLO Monitor Rule" }),
|
|
198
|
+
);
|
|
199
|
+
await waitFor(() => {
|
|
200
|
+
expect(submittedRule).not.toBeNull();
|
|
201
|
+
});
|
|
202
|
+
return submittedRule!;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
beforeEach(() => {
|
|
206
|
+
savedRule = null;
|
|
207
|
+
submittedRule = null;
|
|
208
|
+
selectedFields = {};
|
|
209
|
+
permissions = [Permission.ProjectOwner, Permission.User];
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
afterEach(() => {
|
|
213
|
+
cleanup();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe("SLO monitor rule criteria in the create and edit forms", () => {
|
|
217
|
+
test("lists Monitor Type and names text fields without Pattern", async () => {
|
|
218
|
+
await renderForm();
|
|
219
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
220
|
+
await user.click(screen.getByTestId("rule-criteria-add"));
|
|
221
|
+
await user.click(
|
|
222
|
+
screen.getByRole("combobox", { name: "Criteria for condition 1" }),
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
for (const title of [
|
|
226
|
+
"Monitor Labels",
|
|
227
|
+
"Monitor Type",
|
|
228
|
+
"Monitor Name",
|
|
229
|
+
"Monitor Description",
|
|
230
|
+
]) {
|
|
231
|
+
expect(
|
|
232
|
+
screen.getAllByText(title, { exact: true }).length,
|
|
233
|
+
).toBeGreaterThan(0);
|
|
234
|
+
}
|
|
235
|
+
expect(
|
|
236
|
+
screen.queryByText("Monitor Name Pattern", { exact: true }),
|
|
237
|
+
).toBeNull();
|
|
238
|
+
expect(
|
|
239
|
+
screen.queryByText("Monitor Description Pattern", { exact: true }),
|
|
240
|
+
).toBeNull();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test("offers every valid monitor type as a single dropdown value", async () => {
|
|
244
|
+
await renderForm();
|
|
245
|
+
await addCondition("Monitor Type");
|
|
246
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
247
|
+
await user.click(
|
|
248
|
+
screen.getByRole("combobox", { name: "Value for condition 1" }),
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
for (const monitorType of Object.values(MonitorType)) {
|
|
252
|
+
expect(screen.getByText(monitorType, { exact: true })).not.toBeNull();
|
|
253
|
+
}
|
|
254
|
+
expect(screen.queryByText("No options")).toBeNull();
|
|
255
|
+
|
|
256
|
+
await user.click(screen.getByText(MonitorType.Website, { exact: true }));
|
|
257
|
+
await selectOption("Value for condition 1", MonitorType.API);
|
|
258
|
+
const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
|
|
259
|
+
expect(rule.criteria).toEqual(
|
|
260
|
+
criteriaWith("monitorType", RuleCriteriaOperator.Equals, MonitorType.API),
|
|
261
|
+
);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
test("limits Monitor Type operators to Equals and Does not equal", async () => {
|
|
265
|
+
await renderForm();
|
|
266
|
+
await addCondition("Monitor Type");
|
|
267
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
268
|
+
await user.click(
|
|
269
|
+
screen.getByRole("combobox", { name: "Operator for condition 1" }),
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
expect(
|
|
273
|
+
screen.getAllByText("Equals", { exact: true }).length,
|
|
274
|
+
).toBeGreaterThan(0);
|
|
275
|
+
expect(screen.getByText("Does not equal", { exact: true })).not.toBeNull();
|
|
276
|
+
for (const unsupported of [
|
|
277
|
+
"Contains",
|
|
278
|
+
"Matches pattern",
|
|
279
|
+
"Does not match pattern",
|
|
280
|
+
"Has any of",
|
|
281
|
+
]) {
|
|
282
|
+
expect(screen.queryByText(unsupported, { exact: true })).toBeNull();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
await user.click(screen.getByText("Does not equal", { exact: true }));
|
|
286
|
+
await selectOption("Value for condition 1", MonitorType.Manual);
|
|
287
|
+
const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
|
|
288
|
+
expect(rule.criteria).toEqual(
|
|
289
|
+
criteriaWith(
|
|
290
|
+
"monitorType",
|
|
291
|
+
RuleCriteriaOperator.NotEquals,
|
|
292
|
+
MonitorType.Manual,
|
|
293
|
+
),
|
|
294
|
+
);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test.each([
|
|
298
|
+
["Monitor Name", "monitorNamePattern"],
|
|
299
|
+
["Monitor Description", "monitorDescriptionPattern"],
|
|
300
|
+
])(
|
|
301
|
+
"offers pattern operators for %s and preserves its stored field key",
|
|
302
|
+
async (title: string, field: string) => {
|
|
303
|
+
await renderForm();
|
|
304
|
+
await addCondition(title);
|
|
305
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
306
|
+
await user.click(
|
|
307
|
+
screen.getByRole("combobox", { name: "Operator for condition 1" }),
|
|
308
|
+
);
|
|
309
|
+
expect(
|
|
310
|
+
screen.getAllByText("Matches pattern", { exact: true }).length,
|
|
311
|
+
).toBeGreaterThan(0);
|
|
312
|
+
expect(
|
|
313
|
+
screen.getByText("Does not match pattern", { exact: true }),
|
|
314
|
+
).not.toBeNull();
|
|
315
|
+
expect(screen.getByText("Contains", { exact: true })).not.toBeNull();
|
|
316
|
+
|
|
317
|
+
await user.click(
|
|
318
|
+
screen.getByText("Does not match pattern", { exact: true }),
|
|
319
|
+
);
|
|
320
|
+
await user.type(
|
|
321
|
+
screen.getByTestId("rule-criteria-value-0"),
|
|
322
|
+
"^staging-.*",
|
|
323
|
+
);
|
|
324
|
+
const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
|
|
325
|
+
expect(rule.criteria).toEqual(
|
|
326
|
+
criteriaWith(
|
|
327
|
+
field,
|
|
328
|
+
RuleCriteriaOperator.DoesNotMatchPattern,
|
|
329
|
+
"^staging-.*",
|
|
330
|
+
),
|
|
331
|
+
);
|
|
332
|
+
},
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
test.each([FilterCondition.All, FilterCondition.Any])(
|
|
336
|
+
"combines type and text conditions with Match %s and sends the compatibility shadow",
|
|
337
|
+
async (filterCondition: FilterCondition) => {
|
|
338
|
+
await renderForm();
|
|
339
|
+
await addCondition("Monitor Type");
|
|
340
|
+
await selectOption("Value for condition 1", MonitorType.API);
|
|
341
|
+
await addCondition("Monitor Name");
|
|
342
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
343
|
+
await user.type(screen.getByTestId("rule-criteria-value-1"), "api-*");
|
|
344
|
+
await user.click(
|
|
345
|
+
screen.getByTestId(
|
|
346
|
+
filterCondition === FilterCondition.All
|
|
347
|
+
? "rule-criteria-match-all"
|
|
348
|
+
: "rule-criteria-match-any",
|
|
349
|
+
),
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
|
|
353
|
+
expect(rule.criteria).toEqual({
|
|
354
|
+
schemaVersion: RULE_CRITERIA_SCHEMA_VERSION,
|
|
355
|
+
filterCondition: filterCondition,
|
|
356
|
+
filters: [
|
|
357
|
+
{
|
|
358
|
+
field: "monitorType",
|
|
359
|
+
operator: RuleCriteriaOperator.Equals,
|
|
360
|
+
value: MonitorType.API,
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
field: "monitorNamePattern",
|
|
364
|
+
operator: RuleCriteriaOperator.MatchesPattern,
|
|
365
|
+
value: "api-*",
|
|
366
|
+
},
|
|
367
|
+
],
|
|
368
|
+
});
|
|
369
|
+
expect(rule.monitorType).toBeNull();
|
|
370
|
+
expect(rule.monitorNamePattern).toBe(
|
|
371
|
+
RULE_CRITERIA_LEGACY_NEVER_MATCH_PATTERN,
|
|
372
|
+
);
|
|
373
|
+
expect(rule.monitorDescriptionPattern).toBeNull();
|
|
374
|
+
expect(rule.monitorLabels).toEqual([]);
|
|
375
|
+
},
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
test("prevents saving a Monitor Type condition without choosing a value", async () => {
|
|
379
|
+
await renderForm();
|
|
380
|
+
await addCondition("Monitor Type");
|
|
381
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
382
|
+
await user.click(
|
|
383
|
+
screen.getByRole("button", { name: "Save SLO Monitor Rule" }),
|
|
384
|
+
);
|
|
385
|
+
expect(
|
|
386
|
+
(await screen.findByTestId("rule-criteria-error")).textContent,
|
|
387
|
+
).toContain("non-blank");
|
|
388
|
+
expect(submittedRule).toBeNull();
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test("clears an incompatible pattern when switching to Monitor Type", async () => {
|
|
392
|
+
await renderForm();
|
|
393
|
+
await addCondition("Monitor Name");
|
|
394
|
+
const user: ReturnType<typeof userEvent.setup> = userEvent.setup();
|
|
395
|
+
await user.type(screen.getByTestId("rule-criteria-value-0"), "api-*");
|
|
396
|
+
await selectOption("Criteria for condition 1", "Monitor Type");
|
|
397
|
+
|
|
398
|
+
expect(screen.getByText("Equals", { exact: true })).not.toBeNull();
|
|
399
|
+
expect(screen.queryByDisplayValue("api-*")).toBeNull();
|
|
400
|
+
expect(screen.getByText("Select Monitor Type")).not.toBeNull();
|
|
401
|
+
await selectOption("Value for condition 1", MonitorType.Ping);
|
|
402
|
+
const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
|
|
403
|
+
expect(rule.criteria).toEqual(
|
|
404
|
+
criteriaWith(
|
|
405
|
+
"monitorType",
|
|
406
|
+
RuleCriteriaOperator.Equals,
|
|
407
|
+
MonitorType.Ping,
|
|
408
|
+
),
|
|
409
|
+
);
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
test.each([
|
|
413
|
+
[RuleCriteriaOperator.Equals, MonitorType.DockerSwarm],
|
|
414
|
+
[RuleCriteriaOperator.NotEquals, MonitorType.SSLCertificate],
|
|
415
|
+
])(
|
|
416
|
+
"loads and saves a stored type condition using %s without changing it",
|
|
417
|
+
async (operator: RuleCriteriaOperator, monitorType: MonitorType) => {
|
|
418
|
+
const criteria: RuleCriteria = criteriaWith(
|
|
419
|
+
"monitorType",
|
|
420
|
+
operator,
|
|
421
|
+
monitorType,
|
|
422
|
+
);
|
|
423
|
+
savedRule = existingRule(criteria);
|
|
424
|
+
savedRule.monitorNamePattern = RULE_CRITERIA_LEGACY_NEVER_MATCH_PATTERN;
|
|
425
|
+
await renderForm(FormType.Update);
|
|
426
|
+
|
|
427
|
+
expect(selectedFields).toMatchObject({
|
|
428
|
+
monitorType: true,
|
|
429
|
+
criteria: true,
|
|
430
|
+
});
|
|
431
|
+
const row: HTMLElement = screen.getByTestId("rule-criteria-row-0");
|
|
432
|
+
expect(
|
|
433
|
+
within(row).getByText("Monitor Type", { exact: true }),
|
|
434
|
+
).not.toBeNull();
|
|
435
|
+
expect(
|
|
436
|
+
within(row).getByText(monitorType, { exact: true }),
|
|
437
|
+
).not.toBeNull();
|
|
438
|
+
expect(
|
|
439
|
+
within(row).getByText(
|
|
440
|
+
operator === RuleCriteriaOperator.Equals
|
|
441
|
+
? "Equals"
|
|
442
|
+
: "Does not equal",
|
|
443
|
+
{ exact: true },
|
|
444
|
+
),
|
|
445
|
+
).not.toBeNull();
|
|
446
|
+
const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
|
|
447
|
+
expect(rule._id).toBe(RULE_ID);
|
|
448
|
+
expect(rule.criteria).toEqual(criteria);
|
|
449
|
+
},
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
test("edits a saved type and operator", async () => {
|
|
453
|
+
savedRule = existingRule(
|
|
454
|
+
criteriaWith("monitorType", RuleCriteriaOperator.Equals, MonitorType.API),
|
|
455
|
+
);
|
|
456
|
+
await renderForm(FormType.Update);
|
|
457
|
+
await selectOption("Operator for condition 1", "Does not equal");
|
|
458
|
+
await selectOption("Value for condition 1", MonitorType.Manual);
|
|
459
|
+
const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
|
|
460
|
+
expect(rule.criteria).toEqual(
|
|
461
|
+
criteriaWith(
|
|
462
|
+
"monitorType",
|
|
463
|
+
RuleCriteriaOperator.NotEquals,
|
|
464
|
+
MonitorType.Manual,
|
|
465
|
+
),
|
|
466
|
+
);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
test("hydrates legacy name and description patterns under their new labels", async () => {
|
|
470
|
+
savedRule = existingRule();
|
|
471
|
+
savedRule.monitorNamePattern = "^api-";
|
|
472
|
+
savedRule.monitorDescriptionPattern = "*customer*";
|
|
473
|
+
await renderForm(FormType.Update);
|
|
474
|
+
|
|
475
|
+
expect(screen.getByText("Monitor Name", { exact: true })).not.toBeNull();
|
|
476
|
+
expect(
|
|
477
|
+
screen.getByText("Monitor Description", { exact: true }),
|
|
478
|
+
).not.toBeNull();
|
|
479
|
+
expect(
|
|
480
|
+
screen.getAllByText("Matches pattern", { exact: true }),
|
|
481
|
+
).toHaveLength(2);
|
|
482
|
+
expect(screen.getByDisplayValue("^api-")).not.toBeNull();
|
|
483
|
+
expect(screen.getByDisplayValue("*customer*")).not.toBeNull();
|
|
484
|
+
const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
|
|
485
|
+
expect(rule.criteria).toEqual({
|
|
486
|
+
schemaVersion: RULE_CRITERIA_SCHEMA_VERSION,
|
|
487
|
+
filterCondition: FilterCondition.All,
|
|
488
|
+
filters: [
|
|
489
|
+
{
|
|
490
|
+
field: "monitorNamePattern",
|
|
491
|
+
operator: RuleCriteriaOperator.MatchesPattern,
|
|
492
|
+
value: "^api-",
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
field: "monitorDescriptionPattern",
|
|
496
|
+
operator: RuleCriteriaOperator.MatchesPattern,
|
|
497
|
+
value: "*customer*",
|
|
498
|
+
},
|
|
499
|
+
],
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
test("hydrates a legacy monitor type using Equals", async () => {
|
|
504
|
+
savedRule = existingRule();
|
|
505
|
+
savedRule.monitorType = MonitorType.Server;
|
|
506
|
+
await renderForm(FormType.Update);
|
|
507
|
+
|
|
508
|
+
expect(screen.getByText("Monitor Type", { exact: true })).not.toBeNull();
|
|
509
|
+
expect(screen.getByText("Equals", { exact: true })).not.toBeNull();
|
|
510
|
+
expect(
|
|
511
|
+
screen.getByText(MonitorType.Server, { exact: true }),
|
|
512
|
+
).not.toBeNull();
|
|
513
|
+
const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
|
|
514
|
+
expect(rule.criteria).toEqual(
|
|
515
|
+
criteriaWith(
|
|
516
|
+
"monitorType",
|
|
517
|
+
RuleCriteriaOperator.Equals,
|
|
518
|
+
MonitorType.Server,
|
|
519
|
+
),
|
|
520
|
+
);
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
test("shows Monitor Type to a user with only the specific create permission", async () => {
|
|
524
|
+
permissions = [
|
|
525
|
+
Permission.CreateServiceLevelObjectiveMonitorRule,
|
|
526
|
+
Permission.User,
|
|
527
|
+
];
|
|
528
|
+
await renderForm();
|
|
529
|
+
await addCondition("Monitor Type");
|
|
530
|
+
await selectOption("Value for condition 1", MonitorType.Website);
|
|
531
|
+
const rule: ServiceLevelObjectiveMonitorRule = await submitForm();
|
|
532
|
+
expect(rule.criteria?.filters[0]?.value).toBe(MonitorType.Website);
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
test("uses concise field names and explicit operators in rule summaries", () => {
|
|
536
|
+
const rule: ServiceLevelObjectiveMonitorRule = existingRule({
|
|
537
|
+
schemaVersion: RULE_CRITERIA_SCHEMA_VERSION,
|
|
538
|
+
filterCondition: FilterCondition.All,
|
|
539
|
+
filters: [
|
|
540
|
+
{
|
|
541
|
+
field: "monitorType",
|
|
542
|
+
operator: RuleCriteriaOperator.Equals,
|
|
543
|
+
value: MonitorType.API,
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
field: "monitorNamePattern",
|
|
547
|
+
operator: RuleCriteriaOperator.MatchesPattern,
|
|
548
|
+
value: "api-*",
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
field: "monitorDescriptionPattern",
|
|
552
|
+
operator: RuleCriteriaOperator.DoesNotMatchPattern,
|
|
553
|
+
value: "*staging*",
|
|
554
|
+
},
|
|
555
|
+
],
|
|
556
|
+
});
|
|
557
|
+
expect(
|
|
558
|
+
getRuleCriteriaSummaryText({
|
|
559
|
+
fields: getLegacyRuleCriteriaFields(getSloMonitorRuleFormFields()),
|
|
560
|
+
item: rule,
|
|
561
|
+
}),
|
|
562
|
+
).toBe(
|
|
563
|
+
"Match all: Monitor Type equals “API”; Monitor Name matches pattern “api-*”; Monitor Description does not match pattern “*staging*”",
|
|
564
|
+
);
|
|
565
|
+
});
|
|
566
|
+
});
|
|
@@ -130,15 +130,17 @@ const SUB_MODEL_ID: ObjectID = new ObjectID(
|
|
|
130
130
|
);
|
|
131
131
|
|
|
132
132
|
/*
|
|
133
|
-
* Charts left the menu when its history moved into Metrics. A
|
|
134
|
-
*
|
|
135
|
-
* rule id no menu could know.
|
|
133
|
+
* Charts left the menu when its history moved into Metrics. A rule's view
|
|
134
|
+
* page (monitor, label or owner rule) is reached from its row's View button,
|
|
135
|
+
* not the menu - it has a rule id no menu could know.
|
|
136
136
|
*/
|
|
137
137
|
const SLO_MENU_KEYS: Array<string> = SLO_PAGE_KEYS.filter(
|
|
138
138
|
(key: string): boolean => {
|
|
139
139
|
return (
|
|
140
140
|
key !== PageMap.SLO_VIEW_CHARTS &&
|
|
141
|
-
key !== PageMap.SLO_VIEW_MONITOR_RULE_VIEW
|
|
141
|
+
key !== PageMap.SLO_VIEW_MONITOR_RULE_VIEW &&
|
|
142
|
+
key !== PageMap.SLOS_SETTINGS_LABEL_RULE_VIEW &&
|
|
143
|
+
key !== PageMap.SLOS_SETTINGS_OWNER_RULE_VIEW
|
|
142
144
|
);
|
|
143
145
|
},
|
|
144
146
|
);
|