Skip to content

Commit 1097e3a

Browse files
committed
Add more dashboard item tests
1 parent 5c6b996 commit 1097e3a

File tree

7 files changed

+72
-11
lines changed

7 files changed

+72
-11
lines changed

src/Frontend/src/components/DashboardItem.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ const props = defineProps<{
77
</script>
88

99
<template>
10-
<RouterLink role="dashboard-item" class="summary-item" :class="{ 'summary-danger': counter > 0, 'summary-info': counter === 0 || !counter }" :to="url">
10+
<RouterLink aria-label="Dashboard Item" class="summary-item" :class="{ 'summary-danger': counter > 0, 'summary-info': counter === 0 || !counter }" :to="url">
1111
<i class="fa fa-3x" :class="props.iconClass"> </i>
12-
<span v-if="counter > 0" role="counter" class="badge badge-important">{{ counter }}</span>
12+
<span v-if="counter > 0" aria-label="Alert Count" class="badge badge-important">{{ counter }}</span>
1313
<h4>
1414
<slot></slot>
1515
</h4>

src/Frontend/test/mocks/browser.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { setupWorker } from "msw/browser";
22
import { Driver } from "../driver";
33
import { makeMockEndpoint, makeMockEndpointDynamic } from "../mock-endpoint";
44
import * as precondition from "../preconditions";
5+
import { EndpointsView } from "@/resources/EndpointView";
6+
import { EndpointStatus } from "@/resources/Heartbeat";
57
export const worker = setupWorker();
68
const mockEndpoint = makeMockEndpoint({ mockServer: worker });
79
const mockEndpointDynamic = makeMockEndpointDynamic({ mockServer: worker });
@@ -36,6 +38,11 @@ const driver = makeDriver();
3638
])
3739
);
3840

41+
const unhealthyEndpoint = <EndpointsView>{ is_sending_heartbeats: true, id: "", name: "Dashboard.Item.Test", monitor_heartbeat: true, host_display_name: "", heartbeat_information: { reported_status: EndpointStatus.Dead, last_report_at: "" } };
42+
43+
await driver.setUp(precondition.serviceControlWithMonitoring);
44+
await driver.setUp(precondition.hasHeartbeatsEndpoints([unhealthyEndpoint]));
45+
3946
await driver.setUp(
4047
precondition.hasFailedMessage({
4148
withGroupId: "81dca64e-76fc-e1c3-11a2-3069f51c58c8",

src/Frontend/test/preconditions/hasHeartbeatEndpoints.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { EndpointStatus } from "@/resources/Heartbeat";
12
import { SetupFactoryOptions } from "../driver";
23
import { EndpointsView } from "@/resources/EndpointView";
34

@@ -10,4 +11,21 @@ export const hasHeartbeatsEndpoints =
1011
return endpoints;
1112
};
1213

14+
export const hasUnhealthyHeartbeatsEndpoints = (numberOfUnhealthyEndpoints: number = 1) => {
15+
const unhealthyEndpoints = [];
16+
17+
for (let i = 0; i < numberOfUnhealthyEndpoints; i++) {
18+
unhealthyEndpoints.push(<EndpointsView>{
19+
is_sending_heartbeats: true,
20+
id: "",
21+
name: `UnhealthyHeartbeatEndpoint_${i}`,
22+
monitor_heartbeat: true,
23+
host_display_name: "",
24+
heartbeat_information: { reported_status: EndpointStatus.Dead, last_report_at: "" },
25+
});
26+
}
27+
28+
return hasHeartbeatsEndpoints(unhealthyEndpoints);
29+
};
30+
1331
export const hasNoHeartbeatsEndpoints = hasHeartbeatsEndpoints([]);

src/Frontend/test/preconditions/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export { hasEventLogItems } from "../preconditions/hasEventLogItems";
1212
export { hasRecoverabilityGroups } from "../preconditions/hasEmptyRecoverabilityGroups";
1313
export * from "./hasEndpointsWithHistoryPeriodData";
1414
export * from "./hasMonitoredEndpointDetails";
15-
export { hasNoHeartbeatsEndpoints, hasHeartbeatsEndpoints } from "../preconditions/hasHeartbeatEndpoints";
15+
export { hasNoHeartbeatsEndpoints, hasHeartbeatsEndpoints, hasUnhealthyHeartbeatsEndpoints } from "../preconditions/hasHeartbeatEndpoints";
1616
export { serviceControlWithMonitoring } from "./serviceControlWithMonitoring";
1717
export * from "./recoverability";
1818
export { hasLicensingReportAvailable } from "../preconditions/hasLicensingReportAvailable";
Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,54 @@
11
import { test, describe } from "../../drivers/vitest/driver";
22
import * as precondition from "../../preconditions";
3-
import { expect } from "vitest";
3+
import { expect, vi } from "vitest";
44
import { queryHeartbeatDashboardItem } from "./questions/queryHeartbeatDashboardItem";
5+
import { waitFor } from "@testing-library/vue";
56

67
describe("FEATURE: Dashboard item", () => {
78
describe("RULE: The count of unhealthy endpoints should be displayed", () => {
8-
test("EXAMPLE: Should not display the counter when there are zero unhealthy endpoints", async ({ driver }) => {
9+
test("EXAMPLE: No unhealthy endpoints.", async ({ driver }) => {
10+
vi.useFakeTimers();
911
await driver.setUp(precondition.serviceControlWithMonitoring);
12+
1013
await driver.goTo("dashboard");
1114

15+
vi.advanceTimersByTime(5000);
1216
const heartbeatDashboardItem = await queryHeartbeatDashboardItem();
17+
18+
// Reverse logic here to make sure the heartbeatDashboardItem is defined but the flag is falsey.
1319
expect(heartbeatDashboardItem && !heartbeatDashboardItem.isCounterVisible).toBeTruthy();
20+
21+
vi.useRealTimers();
22+
});
23+
24+
test("EXAMPLE: One unhealthy endpoint.", async ({ driver }) => {
25+
await driver.setUp(precondition.serviceControlWithMonitoring);
26+
await driver.setUp(precondition.hasUnhealthyHeartbeatsEndpoints());
27+
28+
await driver.goTo("dashboard");
29+
30+
await waitFor(async () => {
31+
const heartbeatDashboardItem = await queryHeartbeatDashboardItem();
32+
// check the endpoint data has been updated immediately
33+
expect(heartbeatDashboardItem && heartbeatDashboardItem.isCounterVisible).toBeTruthy();
34+
expect(heartbeatDashboardItem && heartbeatDashboardItem.counterValue).toBe(1);
35+
});
36+
});
37+
38+
test("EXAMPLE: Three unhealthy endpoints.", async ({ driver }) => {
39+
const numberOfUnhealthyEndpoints = 3;
40+
41+
await driver.setUp(precondition.serviceControlWithMonitoring);
42+
await driver.setUp(precondition.hasUnhealthyHeartbeatsEndpoints(numberOfUnhealthyEndpoints));
43+
44+
await driver.goTo("dashboard");
45+
46+
await waitFor(async () => {
47+
const heartbeatDashboardItem = await queryHeartbeatDashboardItem();
48+
49+
expect(heartbeatDashboardItem && heartbeatDashboardItem.isCounterVisible).toBeTruthy();
50+
expect(heartbeatDashboardItem && heartbeatDashboardItem.counterValue).toBe(numberOfUnhealthyEndpoints);
51+
});
1452
});
1553
});
1654
});

src/Frontend/test/specs/heartbeats/questions/getDashboardItems.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,19 @@ export interface DashboardItemData {
88
}
99

1010
export async function getDashboardItems() {
11-
const dashboardItems = await screen.findAllByRole("dashboard-item");
11+
const dashboardItems = await screen.findAllByRole("link", { name: "Dashboard Item" });
1212

1313
return new Map<string, DashboardItemData>(
1414
dashboardItems.map((di) => {
15-
const nameHeading = within(di).getByRole("heading");
16-
const name = String(nameHeading.textContent);
17-
const counterElement = within(di).queryByRole("counter");
15+
const name = String(within(di).getByRole("heading").textContent);
16+
const counterElement = within(di).queryByLabelText("Alert Count");
1817

1918
return [
2019
name,
2120
{
2221
name: name,
2322
isCounterVisible: counterElement !== null,
24-
counterValue: counterElement ? Number(counterElement.innerText) : 0,
23+
counterValue: counterElement ? Number(counterElement.textContent) : 0,
2524
dashboardItem: di,
2625
},
2726
];

src/Frontend/test/specs/heartbeats/questions/queryHeartbeatDashboardItem.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,5 @@ import { getDashboardItems } from "./getDashboardItems";
22

33
export async function queryHeartbeatDashboardItem() {
44
const dashboardItems = await getDashboardItems();
5-
65
return dashboardItems ? dashboardItems.get("Heartbeats") : null;
76
}

0 commit comments

Comments
 (0)