@oneuptime/common 14.0.6 → 14.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/InventoryItem.ts +23 -12
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.ts +217 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Services/AlertService.ts +32 -36
- package/Server/Services/IncidentAlertService.ts +609 -2
- package/Server/Services/IncidentService.ts +134 -44
- package/Server/Services/InventoryItemService.ts +38 -0
- package/Server/Services/IoTDeviceCredentialService.ts +13 -4
- package/Server/Services/ScheduledMaintenanceService.ts +50 -46
- package/Server/Services/UserNotificationRuleService.ts +55 -53
- package/Server/Services/WorkspaceNotificationSummaryService.ts +38 -20
- package/Server/Utils/AffectedResources/LinkedAffectedResources.ts +576 -0
- package/Server/Utils/Alert/AlertStateChangeAuthorization.ts +129 -0
- package/Server/Utils/Inventory/InventoryOverviewAggregation.ts +111 -0
- package/Server/Utils/Response.ts +31 -0
- package/Server/Utils/Topology/TopologyConcurrencyLimiter.ts +229 -0
- package/Server/Utils/Topology/TopologyQueries.ts +1350 -0
- package/Server/Utils/Topology/TopologyRequest.ts +463 -0
- package/Server/Utils/Topology/TopologyResponseCache.ts +183 -0
- package/Server/Utils/Topology/TopologySql.ts +1024 -0
- package/Tests/App/Dashboard/AcknowledgeAlertsOnDeclare.test.ts +369 -0
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +1 -1
- package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +510 -123
- package/Tests/App/Dashboard/AlertsTableAffectedResources.test.tsx +490 -0
- package/Tests/App/Dashboard/ChangeAlertStateDeclareIncident.test.tsx +886 -0
- package/Tests/App/Dashboard/CreateReviewStepRoleSummary.test.tsx +1250 -0
- package/Tests/App/Dashboard/CreateReviewStepSelectionSummary.test.tsx +738 -0
- package/Tests/App/Dashboard/DeclareIncidentFromAlert.test.ts +417 -0
- package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +1948 -229
- package/Tests/App/Dashboard/EntityDetailPanelLifecycle.test.tsx +493 -0
- package/Tests/App/Dashboard/EntityDetailPanelNavigation.test.tsx +439 -0
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +292 -1
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +798 -2
- package/Tests/App/Dashboard/FetchStateAndSeverityElements.test.tsx +669 -0
- package/Tests/App/Dashboard/FetchUsers.test.tsx +230 -0
- package/Tests/App/Dashboard/IncidentCreateAcknowledgeAlerts.test.tsx +1611 -0
- package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +1365 -57
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +964 -23
- package/Tests/App/Dashboard/InventoryRelationships.test.tsx +885 -0
- package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +201 -15
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +508 -36
- package/Tests/App/Dashboard/TopologyDataLifecycle.test.tsx +583 -0
- package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +982 -218
- package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +818 -114
- package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +90 -21
- package/Tests/Server/Services/DomainService.test.ts +525 -0
- package/Tests/Server/Services/IncidentAlertAcknowledgeOnDeclare.test.ts +2630 -0
- package/Tests/Server/Services/IncidentAlertPostgres.test.ts +1625 -1
- package/Tests/Server/Services/IncidentDeclareAcknowledgeAlerts.test.ts +2189 -0
- package/Tests/Server/Services/InventoryItemServiceOverviewCounts.test.ts +345 -0
- package/Tests/Server/Services/InventoryOverviewPostgres.test.ts +254 -0
- package/Tests/Server/Services/IoTDeviceCredentialService.test.ts +819 -0
- package/Tests/Server/Services/LinkedAffectedResourcesCreatedFeed.test.ts +420 -0
- package/Tests/Server/Services/SloAffectedResourceCreatedFeed.test.ts +92 -36
- package/Tests/Server/Utils/AffectedResources/LinkedAffectedResources.test.ts +858 -0
- package/Tests/Server/Utils/Alert/AlertStateChangeAuthorization.test.ts +1172 -0
- package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigration.test.ts +386 -0
- package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigrationPostgres.test.ts +430 -0
- package/Tests/Server/Utils/Topology/TopologyActivityParityPostgres.test.ts +279 -0
- package/Tests/Server/Utils/Topology/TopologyConcurrencyLimiter.test.ts +534 -0
- package/Tests/Server/Utils/Topology/TopologyEstateGenerator.ts +624 -0
- package/Tests/Server/Utils/Topology/TopologyJsonResponse.test.ts +90 -0
- package/Tests/Server/Utils/Topology/TopologyQueries.test.ts +1634 -0
- package/Tests/Server/Utils/Topology/TopologyQueriesDifferentialPostgres.test.ts +683 -0
- package/Tests/Server/Utils/Topology/TopologyQueriesPostgres.test.ts +2624 -0
- package/Tests/Server/Utils/Topology/TopologyReference.ts +1018 -0
- package/Tests/Server/Utils/Topology/TopologyRequest.test.ts +643 -0
- package/Tests/Server/Utils/Topology/TopologyResponseCache.test.ts +305 -0
- package/Tests/Server/Utils/Topology/TopologySql.test.ts +973 -0
- package/Tests/Types/Topology/TopologyTypeRules.test.ts +176 -0
- package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +302 -0
- package/Types/Incident/IncidentAlertLink.ts +19 -0
- package/Types/Telemetry/InventoryLiveness.ts +26 -0
- package/Types/Topology/TopologyApi.ts +428 -0
- package/Types/Topology/TopologyTypeRules.ts +191 -0
- package/Utils/Incident/IncidentFromAlerts.ts +78 -0
- package/build/dist/Models/DatabaseModels/InventoryItem.js +20 -11
- package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js +165 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.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/Services/AlertService.js +21 -33
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/IncidentAlertService.js +457 -3
- package/build/dist/Server/Services/IncidentAlertService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +96 -42
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +31 -0
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/IoTDeviceCredentialService.js +12 -5
- package/build/dist/Server/Services/IoTDeviceCredentialService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +37 -40
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +55 -51
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +42 -25
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
- package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js +405 -0
- package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js.map +1 -0
- package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js +112 -0
- package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js.map +1 -0
- package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js +81 -0
- package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js.map +1 -0
- package/build/dist/Server/Utils/Response.js +30 -0
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js +178 -0
- package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologyQueries.js +884 -0
- package/build/dist/Server/Utils/Topology/TopologyQueries.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologyRequest.js +275 -0
- package/build/dist/Server/Utils/Topology/TopologyRequest.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologyResponseCache.js +146 -0
- package/build/dist/Server/Utils/Topology/TopologyResponseCache.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologySql.js +688 -0
- package/build/dist/Server/Utils/Topology/TopologySql.js.map +1 -0
- package/build/dist/Types/Incident/IncidentAlertLink.js +17 -0
- package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -1
- package/build/dist/Types/Telemetry/InventoryLiveness.js +23 -0
- package/build/dist/Types/Telemetry/InventoryLiveness.js.map +1 -1
- package/build/dist/Types/Topology/TopologyApi.js +55 -0
- package/build/dist/Types/Topology/TopologyApi.js.map +1 -0
- package/build/dist/Types/Topology/TopologyTypeRules.js +165 -0
- package/build/dist/Types/Topology/TopologyTypeRules.js.map +1 -0
- package/build/dist/Utils/Incident/IncidentFromAlerts.js +38 -0
- package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -1
- package/package.json +1 -1
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
waitFor,
|
|
18
18
|
within,
|
|
19
19
|
} from "@testing-library/react";
|
|
20
|
-
import React, { ReactElement, ReactNode } from "react";
|
|
20
|
+
import React, { FunctionComponent, ReactElement, ReactNode } from "react";
|
|
21
21
|
import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
22
22
|
|
|
23
23
|
/*
|
|
@@ -318,6 +318,7 @@ import IncidentState from "../../../Models/DatabaseModels/IncidentState";
|
|
|
318
318
|
import IncidentStateTimeline from "../../../Models/DatabaseModels/IncidentStateTimeline";
|
|
319
319
|
import Monitor from "../../../Models/DatabaseModels/Monitor";
|
|
320
320
|
import Probe from "../../../Models/DatabaseModels/Probe";
|
|
321
|
+
import ServiceLevelObjective from "../../../Models/DatabaseModels/ServiceLevelObjective";
|
|
321
322
|
import AIRunHumanVerdict from "../../../Types/AI/AIRunHumanVerdict";
|
|
322
323
|
import AIRunStatus from "../../../Types/AI/AIRunStatus";
|
|
323
324
|
import Route from "../../../Types/API/Route";
|
|
@@ -326,6 +327,7 @@ import OneUptimeDate from "../../../Types/Date";
|
|
|
326
327
|
import ObjectID from "../../../Types/ObjectID";
|
|
327
328
|
import StatusPageSubscriberNotificationStatus from "../../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
|
328
329
|
import { DetailStyle } from "../../../UI/Components/Detail/Detail";
|
|
330
|
+
import FormFieldSchemaType from "../../../UI/Components/Forms/Types/FormFieldSchemaType";
|
|
329
331
|
import Navigation from "../../../UI/Utils/Navigation";
|
|
330
332
|
|
|
331
333
|
const EVENT_ID: string = "11111111-1111-4111-8111-111111111111";
|
|
@@ -1849,6 +1851,90 @@ describe.each([
|
|
|
1849
1851
|
});
|
|
1850
1852
|
});
|
|
1851
1853
|
|
|
1854
|
+
/*
|
|
1855
|
+
* The Affected Resources card. CardModelDetail is stubbed, so the card's
|
|
1856
|
+
* display field is read from its latest props and rendered here the way the
|
|
1857
|
+
* real card renders it. AffectedResourcesDisplay is stubbed for the page too,
|
|
1858
|
+
* so the element its getElement returns is re-rendered with the real
|
|
1859
|
+
* display: what is asserted is what a reader of the card would see.
|
|
1860
|
+
*/
|
|
1861
|
+
interface ResourcesFormFieldProps {
|
|
1862
|
+
field?: Record<string, unknown>;
|
|
1863
|
+
fieldType?: FormFieldSchemaType;
|
|
1864
|
+
showIf?: (values: unknown) => boolean;
|
|
1865
|
+
getCustomElement?: (values: unknown, elementProps: unknown) => ReactElement;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
interface ResourcesCardProps {
|
|
1869
|
+
cardProps: { description?: string };
|
|
1870
|
+
formFields: Array<ResourcesFormFieldProps>;
|
|
1871
|
+
modelDetailProps: { fields: Array<DetailFieldProps> };
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
type ResourcesCardFunction = () => ResourcesCardProps;
|
|
1875
|
+
|
|
1876
|
+
const resourcesCard: ResourcesCardFunction = (): ResourcesCardProps => {
|
|
1877
|
+
return latestProps<ResourcesCardProps>("CardModelDetail:Affected Resources");
|
|
1878
|
+
};
|
|
1879
|
+
|
|
1880
|
+
type ResourcesDisplayFieldFunction = () => DetailFieldProps;
|
|
1881
|
+
|
|
1882
|
+
const resourcesDisplayField: ResourcesDisplayFieldFunction =
|
|
1883
|
+
(): DetailFieldProps => {
|
|
1884
|
+
const displayField: DetailFieldProps | undefined =
|
|
1885
|
+
resourcesCard().modelDetailProps.fields.find(
|
|
1886
|
+
(field: DetailFieldProps): boolean => {
|
|
1887
|
+
return Boolean(field.getElement);
|
|
1888
|
+
},
|
|
1889
|
+
);
|
|
1890
|
+
|
|
1891
|
+
if (!displayField) {
|
|
1892
|
+
throw new Error("The Affected Resources card has no display field");
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
return displayField;
|
|
1896
|
+
};
|
|
1897
|
+
|
|
1898
|
+
type RenderResourcesDisplayFunction = (item: Incident | Alert) => RenderResult;
|
|
1899
|
+
|
|
1900
|
+
const renderResourcesDisplay: RenderResourcesDisplayFunction = (
|
|
1901
|
+
item: Incident | Alert,
|
|
1902
|
+
): RenderResult => {
|
|
1903
|
+
const RealAffectedResourcesDisplay: FunctionComponent<
|
|
1904
|
+
Record<string, unknown>
|
|
1905
|
+
> = (
|
|
1906
|
+
jest.requireActual(
|
|
1907
|
+
"../../../../App/FeatureSet/Dashboard/src/Components/AffectedResources/AffectedResourcesDisplay",
|
|
1908
|
+
) as { default: FunctionComponent<Record<string, unknown>> }
|
|
1909
|
+
).default;
|
|
1910
|
+
|
|
1911
|
+
const display: ReactElement = resourcesDisplayField().getElement!(item);
|
|
1912
|
+
|
|
1913
|
+
return render(
|
|
1914
|
+
<RealAffectedResourcesDisplay
|
|
1915
|
+
{...(display.props as Record<string, unknown>)}
|
|
1916
|
+
/>,
|
|
1917
|
+
);
|
|
1918
|
+
};
|
|
1919
|
+
|
|
1920
|
+
type NamedMonitorFunction = (name: string) => Monitor;
|
|
1921
|
+
|
|
1922
|
+
const namedMonitor: NamedMonitorFunction = (name: string): Monitor => {
|
|
1923
|
+
const monitor: Monitor = new Monitor();
|
|
1924
|
+
monitor.id = new ObjectID(MONITOR_ID);
|
|
1925
|
+
monitor.name = name;
|
|
1926
|
+
return monitor;
|
|
1927
|
+
};
|
|
1928
|
+
|
|
1929
|
+
type NamedSloFunction = (name: string) => ServiceLevelObjective;
|
|
1930
|
+
|
|
1931
|
+
const namedSlo: NamedSloFunction = (name: string): ServiceLevelObjective => {
|
|
1932
|
+
const slo: ServiceLevelObjective = new ServiceLevelObjective();
|
|
1933
|
+
slo.id = new ObjectID("dddddddd-dddd-4ddd-8ddd-ddddddddddd1");
|
|
1934
|
+
slo.name = name;
|
|
1935
|
+
return slo;
|
|
1936
|
+
};
|
|
1937
|
+
|
|
1852
1938
|
describe("incident-only behaviour", () => {
|
|
1853
1939
|
test("the header names who declared the incident once the details card has read it", async () => {
|
|
1854
1940
|
serve(INCIDENT_CASE, {
|
|
@@ -2301,6 +2387,42 @@ describe("incident-only behaviour", () => {
|
|
|
2301
2387
|
})?.value,
|
|
2302
2388
|
).toBe("Probe AP");
|
|
2303
2389
|
});
|
|
2390
|
+
|
|
2391
|
+
/*
|
|
2392
|
+
* The alert card's counterpart: Incident.monitors is ManyToMany and was
|
|
2393
|
+
* always read and shown here, so the two cards agree on what an affected
|
|
2394
|
+
* monitor looks like.
|
|
2395
|
+
*/
|
|
2396
|
+
test("the Affected Resources card reads the incident's monitors and lists them under Monitors", async () => {
|
|
2397
|
+
serve(INCIDENT_CASE, {
|
|
2398
|
+
timeline: REOPENED_TIMELINE,
|
|
2399
|
+
title: "Checkout slow",
|
|
2400
|
+
});
|
|
2401
|
+
|
|
2402
|
+
INCIDENT_CASE.renderPage();
|
|
2403
|
+
await waitForPage();
|
|
2404
|
+
|
|
2405
|
+
expect(resourcesDisplayField().field?.["monitors"]).toEqual({
|
|
2406
|
+
name: true,
|
|
2407
|
+
_id: true,
|
|
2408
|
+
});
|
|
2409
|
+
|
|
2410
|
+
const incident: Incident = new Incident();
|
|
2411
|
+
incident.monitors = [namedMonitor("Developer portal")];
|
|
2412
|
+
|
|
2413
|
+
const view: RenderResult = renderResourcesDisplay(incident);
|
|
2414
|
+
const grid: HTMLElement = within(view.container).getByTestId(
|
|
2415
|
+
"affected-resources-grid",
|
|
2416
|
+
);
|
|
2417
|
+
|
|
2418
|
+
expect(within(view.container).queryByText("No resources affected.")).toBe(
|
|
2419
|
+
null,
|
|
2420
|
+
);
|
|
2421
|
+
expect(within(grid).getByText("Monitors")).toBeInTheDocument();
|
|
2422
|
+
expect(within(grid).getByTestId("monitor-element")).toHaveTextContent(
|
|
2423
|
+
"Developer portal",
|
|
2424
|
+
);
|
|
2425
|
+
});
|
|
2304
2426
|
});
|
|
2305
2427
|
|
|
2306
2428
|
describe("alert-only behaviour", () => {
|
|
@@ -2447,4 +2569,173 @@ describe("alert-only behaviour", () => {
|
|
|
2447
2569
|
).toEqual(["Created"]);
|
|
2448
2570
|
}
|
|
2449
2571
|
});
|
|
2572
|
+
|
|
2573
|
+
/*
|
|
2574
|
+
* An alert is raised on one monitor (Alert.monitor, singular, set when the
|
|
2575
|
+
* alert is created), and the alert's "created" feed item lists that
|
|
2576
|
+
* monitor under Resources Affected. The Affected Resources card used to
|
|
2577
|
+
* hide monitors and never read the relation, so an alert raised on the
|
|
2578
|
+
* "Developer portal" monitor said "No resources affected." right beside a
|
|
2579
|
+
* feed item naming that monitor.
|
|
2580
|
+
*/
|
|
2581
|
+
describe("the Affected Resources card", () => {
|
|
2582
|
+
beforeEach(async () => {
|
|
2583
|
+
serve(ALERT_CASE, {
|
|
2584
|
+
timeline: REOPENED_TIMELINE,
|
|
2585
|
+
title: "Checkout slow",
|
|
2586
|
+
});
|
|
2587
|
+
|
|
2588
|
+
ALERT_CASE.renderPage();
|
|
2589
|
+
await waitForPage();
|
|
2590
|
+
});
|
|
2591
|
+
|
|
2592
|
+
test("reads the alert's monitor alongside the other resources", () => {
|
|
2593
|
+
const select: Record<string, unknown> =
|
|
2594
|
+
resourcesDisplayField().field || {};
|
|
2595
|
+
|
|
2596
|
+
expect(select["monitor"]).toEqual({ name: true, _id: true });
|
|
2597
|
+
expect(select).toEqual(
|
|
2598
|
+
expect.objectContaining({
|
|
2599
|
+
hosts: { name: true, _id: true },
|
|
2600
|
+
services: { name: true, _id: true, serviceColor: true },
|
|
2601
|
+
serviceLevelObjectives: { name: true, _id: true },
|
|
2602
|
+
}),
|
|
2603
|
+
);
|
|
2604
|
+
});
|
|
2605
|
+
|
|
2606
|
+
test("lists the monitor an alert was raised on under Monitors, never 'No resources affected.'", () => {
|
|
2607
|
+
const alert: Alert = new Alert();
|
|
2608
|
+
alert.monitor = namedMonitor("Developer portal");
|
|
2609
|
+
|
|
2610
|
+
const view: RenderResult = renderResourcesDisplay(alert);
|
|
2611
|
+
|
|
2612
|
+
expect(
|
|
2613
|
+
within(view.container).queryByText("No resources affected."),
|
|
2614
|
+
).toBeNull();
|
|
2615
|
+
|
|
2616
|
+
const grid: HTMLElement = within(view.container).getByTestId(
|
|
2617
|
+
"affected-resources-grid",
|
|
2618
|
+
);
|
|
2619
|
+
|
|
2620
|
+
expect(grid.children).toHaveLength(1);
|
|
2621
|
+
expect(within(grid).getByText("Monitors")).toBeInTheDocument();
|
|
2622
|
+
expect(
|
|
2623
|
+
within(grid).getByTestId("affected-resource-item"),
|
|
2624
|
+
).toHaveAttribute("title", "Developer portal");
|
|
2625
|
+
expect(within(grid).getByTestId("monitor-element")).toHaveTextContent(
|
|
2626
|
+
"Developer portal",
|
|
2627
|
+
);
|
|
2628
|
+
expect(within(view.container).getByText("1 resource")).toBeVisible();
|
|
2629
|
+
});
|
|
2630
|
+
|
|
2631
|
+
test("shows both the monitor and an SLO, the monitor first", () => {
|
|
2632
|
+
const alert: Alert = new Alert();
|
|
2633
|
+
alert.monitor = namedMonitor("Developer portal");
|
|
2634
|
+
alert.serviceLevelObjectives = [namedSlo("Checkout availability")];
|
|
2635
|
+
|
|
2636
|
+
const view: RenderResult = renderResourcesDisplay(alert);
|
|
2637
|
+
const grid: HTMLElement = within(view.container).getByTestId(
|
|
2638
|
+
"affected-resources-grid",
|
|
2639
|
+
);
|
|
2640
|
+
const categories: Array<HTMLElement> = Array.from(
|
|
2641
|
+
grid.children,
|
|
2642
|
+
) as Array<HTMLElement>;
|
|
2643
|
+
|
|
2644
|
+
expect(categories).toHaveLength(2);
|
|
2645
|
+
expect(within(categories[0]!).getByText("Monitors")).toBeVisible();
|
|
2646
|
+
expect(
|
|
2647
|
+
within(categories[0]!).getByTestId("monitor-element"),
|
|
2648
|
+
).toHaveTextContent("Developer portal");
|
|
2649
|
+
expect(within(categories[1]!).getByText("SLOs")).toBeVisible();
|
|
2650
|
+
expect(
|
|
2651
|
+
within(categories[1]!).getByText("Checkout availability"),
|
|
2652
|
+
).toBeVisible();
|
|
2653
|
+
expect(within(view.container).getByText("2 resources")).toBeVisible();
|
|
2654
|
+
expect(
|
|
2655
|
+
within(view.container).getByText("across 2 categories"),
|
|
2656
|
+
).toBeVisible();
|
|
2657
|
+
});
|
|
2658
|
+
|
|
2659
|
+
test("an alert with no monitor and nothing else is still 'No resources affected.'", () => {
|
|
2660
|
+
const view: RenderResult = renderResourcesDisplay(new Alert());
|
|
2661
|
+
|
|
2662
|
+
expect(
|
|
2663
|
+
within(view.container).getByText("No resources affected."),
|
|
2664
|
+
).toBeVisible();
|
|
2665
|
+
expect(
|
|
2666
|
+
within(view.container).queryByTestId("affected-resources-grid"),
|
|
2667
|
+
).toBeNull();
|
|
2668
|
+
expect(within(view.container).queryByTestId("monitor-element")).toBe(
|
|
2669
|
+
null,
|
|
2670
|
+
);
|
|
2671
|
+
});
|
|
2672
|
+
|
|
2673
|
+
/*
|
|
2674
|
+
* The monitor is shown, never edited: ModelForm loads and saves only the
|
|
2675
|
+
* fields registered here, so leaving the monitor out means saving the
|
|
2676
|
+
* card can neither move the alert to another monitor nor clear it.
|
|
2677
|
+
*/
|
|
2678
|
+
test("its edit form never loads the monitor, so saving cannot change or clear it", () => {
|
|
2679
|
+
const formFields: Array<ResourcesFormFieldProps> =
|
|
2680
|
+
resourcesCard().formFields;
|
|
2681
|
+
const keysOf: (field: ResourcesFormFieldProps) => Array<string> = (
|
|
2682
|
+
field: ResourcesFormFieldProps,
|
|
2683
|
+
): Array<string> => {
|
|
2684
|
+
return Object.keys(field.field || {});
|
|
2685
|
+
};
|
|
2686
|
+
|
|
2687
|
+
const formKeys: Array<string> = formFields.flatMap(keysOf);
|
|
2688
|
+
|
|
2689
|
+
expect(formKeys).not.toContain("monitor");
|
|
2690
|
+
expect(formKeys).not.toContain("monitors");
|
|
2691
|
+
|
|
2692
|
+
const visibleFields: Array<ResourcesFormFieldProps> = formFields.filter(
|
|
2693
|
+
(field: ResourcesFormFieldProps): boolean => {
|
|
2694
|
+
return !field.showIf || field.showIf({});
|
|
2695
|
+
},
|
|
2696
|
+
);
|
|
2697
|
+
const hiddenFields: Array<ResourcesFormFieldProps> = formFields.filter(
|
|
2698
|
+
(field: ResourcesFormFieldProps): boolean => {
|
|
2699
|
+
return Boolean(field.showIf) && !field.showIf!({});
|
|
2700
|
+
},
|
|
2701
|
+
);
|
|
2702
|
+
|
|
2703
|
+
// The one visible field is the resource picker, registered on hosts.
|
|
2704
|
+
expect(visibleFields.map(keysOf)).toEqual([["hosts"]]);
|
|
2705
|
+
expect(visibleFields[0]!.fieldType).toBe(
|
|
2706
|
+
FormFieldSchemaType.CustomComponent,
|
|
2707
|
+
);
|
|
2708
|
+
// Hidden registrations so the form still loads the other relations.
|
|
2709
|
+
expect(hiddenFields.flatMap(keysOf)).toEqual([
|
|
2710
|
+
"kubernetesClusters",
|
|
2711
|
+
"dockerHosts",
|
|
2712
|
+
"podmanHosts",
|
|
2713
|
+
"proxmoxClusters",
|
|
2714
|
+
"vmwareVCenters",
|
|
2715
|
+
"cephClusters",
|
|
2716
|
+
"dockerSwarmClusters",
|
|
2717
|
+
"iotFleets",
|
|
2718
|
+
"databaseServers",
|
|
2719
|
+
"services",
|
|
2720
|
+
]);
|
|
2721
|
+
|
|
2722
|
+
// The picker it renders offers no monitors to attach either.
|
|
2723
|
+
render(visibleFields[0]!.getCustomElement!({}, {}));
|
|
2724
|
+
|
|
2725
|
+
const picker: { monitors?: unknown; resourceTypes?: Array<string> } =
|
|
2726
|
+
latestProps<{ monitors?: unknown; resourceTypes?: Array<string> }>(
|
|
2727
|
+
"AffectedResourcesPicker",
|
|
2728
|
+
);
|
|
2729
|
+
|
|
2730
|
+
expect(picker.monitors).toBeUndefined();
|
|
2731
|
+
expect(picker.resourceTypes).toContain("Host");
|
|
2732
|
+
expect(picker.resourceTypes).not.toContain("Monitor");
|
|
2733
|
+
});
|
|
2734
|
+
|
|
2735
|
+
test("says it covers monitors", () => {
|
|
2736
|
+
expect(resourcesCard().cardProps.description).toBe(
|
|
2737
|
+
"Monitors, services, infrastructure and SLOs this alert affects.",
|
|
2738
|
+
);
|
|
2739
|
+
});
|
|
2740
|
+
});
|
|
2450
2741
|
});
|