Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dashboard acceptance tests #2208

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Frontend/src/components/DashboardItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ const props = defineProps<{
</script>

<template>
<RouterLink class="summary-item" :class="{ 'summary-danger': counter > 0, 'summary-info': counter === 0 || !counter }" :to="url">
<RouterLink aria-label="Dashboard Item" class="summary-item" :class="{ 'summary-danger': counter > 0, 'summary-info': counter === 0 || !counter }" :to="url">
<i class="fa fa-3x" :class="props.iconClass"> </i>
<span v-if="counter > 0" class="badge badge-important">{{ counter }}</span>
<span v-if="counter > 0" aria-label="Alert Count" class="badge badge-important">{{ counter }}</span>
<h4>
<slot></slot>
</h4>
Expand Down
2 changes: 1 addition & 1 deletion src/Frontend/src/components/NoData.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const props = defineProps<{
<div class="col-sm-12">
<div class="row box-header">
<div class="col-sm-12">
<p class="lead hard-wrap">{{ props.message }}</p>
<p class="lead hard-wrap" role="status">{{ props.message }}</p>
<slot>
<p>&nbsp;</p>
</slot>
Expand Down
2 changes: 1 addition & 1 deletion src/Frontend/src/components/OnOffSwitch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const emit = defineEmits<{ toggle: [] }>();

<template>
<div class="onoffswitch">
<input type="checkbox" :id="`onoffswitch${id}`" :name="`onoffswitch${id}`" class="onoffswitch-checkbox" @click="emit('toggle')" :checked="value ?? false" />
<input type="checkbox" :id="`onoffswitch${id}`" :name="`onoffswitch${id}`" :aria-label="`onoffswitch${id}`" class="onoffswitch-checkbox" @click="emit('toggle')" :checked="value ?? false" />
<label class="onoffswitch-label" :for="`onoffswitch${id}`">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
Expand Down
7 changes: 4 additions & 3 deletions src/Frontend/src/components/TimeSince.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import moment from "moment";

const emptyDate = "0001-01-01T00:00:00";

const props = withDefaults(defineProps<{ dateUtc?: string; defaultTextOnFailure?: string }>(), { dateUtc: emptyDate, defaultTextOnFailure: "n/a" });
const props = withDefaults(defineProps<{ dateUtc?: string; defaultTextOnFailure?: string; titleValue?: string }>(), { dateUtc: emptyDate, defaultTextOnFailure: "n/a", titleValue: undefined });

let interval: number | undefined = undefined;

Expand All @@ -15,9 +15,10 @@ function updateText() {
if (props.dateUtc != null && props.dateUtc !== emptyDate) {
const m = moment.utc(props.dateUtc);
text.value = m.fromNow();
title.value = m.local().format("LLLL") + " (local)\n" + m.utc().format("LLLL") + " (UTC)";
title.value = props.titleValue ?? m.local().format("LLLL") + " (local)\n" + m.utc().format("LLLL") + " (UTC)";
} else {
text.value = title.value = props.defaultTextOnFailure;
text.value = props.defaultTextOnFailure;
title.value = props.titleValue ?? props.defaultTextOnFailure;
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Frontend/src/components/heartbeats/EndpointInstances.vue
Original file line number Diff line number Diff line change
Expand Up @@ -207,12 +207,12 @@ async function toggleAlerts(instance: EndpointsView) {
<template #data="{ pageData }">
<div role="rowgroup" aria-label="endpoints">
<div role="row" :aria-label="instance.name" class="row grid-row" v-for="instance in pageData" :key="instance.id">
<div role="cell" aria-label="instance-name" class="col-6 host-name">
<div role="cell" class="col-6 host-name">
<span role="status" class="status-icon">
<i v-if="instance.heartbeat_information?.reported_status !== EndpointStatus.Alive" aria-label="instance dead" class="fa fa-heartbeat text-danger" />
<i v-else aria-label="instance alive" class="fa fa-heartbeat text-success" />
</span>
<span class="lead">{{ instance.host_display_name }}</span>
<span class="lead" aria-label="instance-name">{{ instance.host_display_name }}</span>
</div>
<div role="cell" aria-label="last-heartbeat" class="col-2 last-heartbeat">
<LastHeartbeat :date="instance.heartbeat_information?.last_report_at" tooltip-target="instance" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const { healthyEndpoints, filteredHealthyEndpoints } = storeToRefs(store);
<div class="row">
<ResultsCount :displayed="filteredHealthyEndpoints.length" :total="healthyEndpoints.length" />
</div>
<section name="healthy_endpoints">
<section name="healthy_endpoints" aria-label="Healthy Endpoints">
<no-data v-if="healthyEndpoints.length === 0" message="No healthy endpoints"></no-data>
<div v-if="healthyEndpoints.length > 0" class="row">
<div class="col-sm-12 no-side-padding">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ async function toggleDefaultSetting() {
<div class="row">
<ResultsCount :displayed="filteredEndpoints.length" :total="sortedEndpoints.length" />
</div>
<section name="endpoint_configuration">
<section name="endpoint_configuration" aria-label="Endpoint Configuration">
<div class="row">
<div class="col-9 no-side-padding">
<no-data v-if="sortedEndpoints.length === 0" message="Nothing to configure" />
Expand Down
10 changes: 5 additions & 5 deletions src/Frontend/src/components/heartbeats/HeartbeatsList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function endpointHealth(endpoint: LogicalEndpoint) {
</tippy>
</div>
</div>
<div v-if="columns.includes(ColumnNames.InstancesTotal) || columns.includes(ColumnNames.InstancesDown)" role="cell" aria-label="instance-count" class="col-2">
<div v-if="columns.includes(ColumnNames.InstancesTotal) || columns.includes(ColumnNames.InstancesDown)" role="cell" class="col-2">
<tippy :delay="[300, 0]">
<template #content>
<template v-if="endpoint.track_instances">
Expand All @@ -96,15 +96,15 @@ function endpointHealth(endpoint: LogicalEndpoint) {
</template>
<i v-if="endpoint.track_instances" class="fa fa-server" :class="endpointHealth(endpoint)"></i>
<i v-else class="fa fa-sellsy" :class="endpointHealth(endpoint)"></i>&nbsp;
<span class="endpoint-count">{{ store.instanceDisplayText(endpoint) }}</span>
<span class="endpoint-count" aria-label="instance-count">{{ store.instanceDisplayText(endpoint) }}</span>
</tippy>
</div>
<div v-if="columns.includes(ColumnNames.LastHeartbeat)" role="cell" aria-label="last-heartbeat" class="col-2 last-heartbeat">
<LastHeartbeat :date="endpoint.heartbeat_information?.last_report_at" tooltip-target="endpoint" />
</div>
<div v-if="columns.includes(ColumnNames.Tracked)" role="cell" aria-label="tracked-instances" class="col-1 centre">
<tippy v-if="endpoint.track_instances" content="Instances are being tracked" :delay="[1000, 0]">
<i class="fa fa-check text-success"></i>
<tippy v-if="endpoint.track_instances" id="tracked-instance-desc" content="Instances are being tracked" :delay="[1000, 0]">
<i class="fa fa-check text-success" aria-title="Instances are being tracked"></i>
</tippy>
</div>
<div v-if="columns.includes(ColumnNames.TrackToggle)" role="cell" aria-label="tracked-instances" class="col-2 centre">
Expand All @@ -117,7 +117,7 @@ function endpointHealth(endpoint: LogicalEndpoint) {
<tippy content="All instances have alerts muted" :delay="[300, 0]">
<i class="fa fa-bell-slash text-danger" />
</tippy>
<span class="instances-muted">{{ endpoint.muted_count }}</span>
<span class="instances-muted" aria-label="Muted instance count">{{ endpoint.muted_count }}</span>
</template>
<template v-else-if="endpoint.muted_count > 0">
<tippy :content="`${endpoint.muted_count} instance(s) have alerts muted`" :delay="[300, 0]">
Expand Down
4 changes: 2 additions & 2 deletions src/Frontend/src/components/heartbeats/HeartbeatsMenuItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ const { failedHeartbeatsCount } = storeToRefs(useHeartbeatsStore());
</script>

<template>
<RouterLink :to="routeLinks.heartbeats.root">
<RouterLink aria-label="Heartbeats Menu Item" :to="routeLinks.heartbeats.root">
<i class="fa fa-heartbeat icon-white" title="Heartbeats"></i>
<span class="navbar-label">Heartbeats</span>
<span v-if="failedHeartbeatsCount > 0" class="badge badge-important">{{ failedHeartbeatsCount }}</span>
<span v-if="failedHeartbeatsCount > 0" class="badge badge-important" aria-label="Alert Count">{{ failedHeartbeatsCount }}</span>
</RouterLink>
</template>

Expand Down
4 changes: 2 additions & 2 deletions src/Frontend/src/components/heartbeats/LastHeartbeat.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ defineProps<{ date?: string; tooltipTarget: string }>();
</script>

<template>
<p v-if="date"><time-since :date-utc="date" default-text-on-failure="unknown" /></p>
<p v-if="date"><time-since :date-utc="date" default-text-on-failure="unknown" title-value="Last Heartbeat" /></p>
<p v-else>
<tippy :delay="[1000, 300]" :interactive="true">
<template #content>
<p>No heartbeat data received for this {{ tooltipTarget }}.</p>
<p>Have you installed and configured the <a target="_blank" href="https://docs.particular.net/monitoring/heartbeats/install-plugin">heartbeats plugin</a> for this {{ tooltipTarget }}?</p>
</template>
<div>No data available</div>
<span title="Last Heartbeat">No data available</span>
</tippy>
</p>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const { unhealthyEndpoints, filteredUnhealthyEndpoints } = storeToRefs(store);
<div class="row">
<ResultsCount :displayed="filteredUnhealthyEndpoints.length" :total="unhealthyEndpoints.length" />
</div>
<section name="unhealthy_endpoints">
<section name="unhealthy_endpoints" aria-label="Unhealthy Endpoints">
<no-data v-if="unhealthyEndpoints.length === 0" message="No unhealthy endpoints"></no-data>
<div v-else class="row">
<div class="col-sm-12 no-side-padding">
Expand Down
7 changes: 3 additions & 4 deletions src/Frontend/src/stores/HeartbeatsStore.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ import { EndpointStatus } from "@/resources/Heartbeat";
import { ColumnNames, useHeartbeatsStore } from "@/stores/HeartbeatsStore";

describe("HeartbeatsStore tests", () => {
async function setup(endpoints: EndpointsView[], endpointSettings: EndpointSettings[], preSetup: (driver: Driver) => Promise<void> = () => Promise.resolve()) {
async function setup(endpoints: EndpointsView[], endpointSettings: EndpointSettings[] = [{ name: "", track_instances: true }], preSetup: (driver: Driver) => Promise<void> = () => Promise.resolve()) {
const driver = makeDriverForTests();

await preSetup(driver);
await driver.setUp(serviceControlWithHeartbeats);
await driver.setUp(precondition.hasEndpointSettings(endpointSettings));
await driver.setUp(precondition.hasHeartbeatsEndpoints(endpoints));
await driver.setUp(precondition.hasHeartbeatsEndpoints(endpoints, endpointSettings));

useServiceControlUrls();
await useServiceControl();
Expand All @@ -34,7 +33,7 @@ describe("HeartbeatsStore tests", () => {
}

test("no endpoints", async () => {
const { filteredHealthyEndpoints, filteredUnhealthyEndpoints } = await setup([], []);
const { filteredHealthyEndpoints, filteredUnhealthyEndpoints } = await setup([]);

expect(filteredHealthyEndpoints.value.length).toBe(0);
expect(filteredUnhealthyEndpoints.value.length).toBe(0);
Expand Down
8 changes: 4 additions & 4 deletions src/Frontend/src/views/HeartbeatsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ const isMassTransitConnected = useIsMassTransitConnected();
</div>
<div class="row">
<div class="col-sm-12">
<div class="tabs">
<div class="tabs" role="tablist">
<div>
<!--Inactive Endpoints-->
<h5 :class="{ active: isRouteSelected(routeLinks.heartbeats.unhealthy.link) }">
<RouterLink :to="routeLinks.heartbeats.unhealthy.link"> Unhealthy Endpoints ({{ unhealthyEndpoints.length }}) </RouterLink>
<RouterLink role="tab" :aria-selected="isRouteSelected(routeLinks.heartbeats.unhealthy.link)" :to="routeLinks.heartbeats.unhealthy.link"> Unhealthy Endpoints ({{ unhealthyEndpoints.length }}) </RouterLink>
</h5>

<!--Active Endpoints-->
<h5 :class="{ active: isRouteSelected(routeLinks.heartbeats.healthy.link) }">
<RouterLink :to="routeLinks.heartbeats.healthy.link"> Healthy Endpoints ({{ healthyEndpoints.length }}) </RouterLink>
<RouterLink role="tab" :aria-selected="isRouteSelected(routeLinks.heartbeats.healthy.link)" :to="routeLinks.heartbeats.healthy.link"> Healthy Endpoints ({{ healthyEndpoints.length }}) </RouterLink>
</h5>

<!--Configuration-->
<h5 :class="{ active: isRouteSelected(routeLinks.heartbeats.configuration.link) }">
<RouterLink :to="routeLinks.heartbeats.configuration.link"> Configuration </RouterLink>
<RouterLink role="tab" :aria-selected="isRouteSelected(routeLinks.heartbeats.configuration.link)" :to="routeLinks.heartbeats.configuration.link"> Configuration </RouterLink>
</h5>
</div>
<div class="filter-group">
Expand Down
22 changes: 2 additions & 20 deletions src/Frontend/test/mocks/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { setupWorker } from "msw/browser";
import { Driver } from "../driver";
import { makeMockEndpoint, makeMockEndpointDynamic } from "../mock-endpoint";
import * as precondition from "../preconditions";

export const worker = setupWorker();
const mockEndpoint = makeMockEndpoint({ mockServer: worker });
const mockEndpointDynamic = makeMockEndpointDynamic({ mockServer: worker });
Expand All @@ -24,24 +25,5 @@ const driver = makeDriver();

(async () => {
await driver.setUp(precondition.serviceControlWithMonitoring);
//override the default mocked endpoints with a custom list
await driver.setUp(
precondition.monitoredEndpointsNamed([
"Universe.Solarsystem.Mercury.Endpoint1",
"Universe.Solarsystem.Mercury.Endpoint2",
"Universe.Solarsystem.Venus.Endpoint3",
"Universe.Solarsystem.Venus.Endpoint4",
"Universe.Solarsystem.Earth.Endpoint5",
"Universe.Solarsystem.Earth.Endpoint6",
])
);

await driver.setUp(
precondition.hasFailedMessage({
withGroupId: "81dca64e-76fc-e1c3-11a2-3069f51c58c8",
withMessageId: "40134401-bab9-41aa-9acb-b19c0066f22d",
withContentType: "application/json",
withBody: { Index: 0, Data: "" },
})
);
await driver.setUp(precondition.HasHealthyAndUnHealthyEndpoints(1, 1));
})();
20 changes: 20 additions & 0 deletions src/Frontend/test/mocks/heartbeat-endpoint-template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { EndpointsView } from "@/resources/EndpointView";
import { EndpointStatus } from "@/resources/Heartbeat";

export const healthyEndpointTemplate = <EndpointsView>{
is_sending_heartbeats: true,
id: "HealthyEndpoint",
name: "HealthyEndpoint",
monitor_heartbeat: true,
host_display_name: "HealhtyEndpoint.Hostname",
heartbeat_information: { reported_status: EndpointStatus.Alive, last_report_at: new Date().toISOString() },
};

export const unHealthyEndpointTemplate = <EndpointsView>{
is_sending_heartbeats: true,
id: "UnHealthyEndpoint",
name: `UnHealthyEndpoint`,
monitor_heartbeat: true,
host_display_name: "UnHealhtyEndpoint.Hostname",
heartbeat_information: { reported_status: EndpointStatus.Dead, last_report_at: new Date().toISOString() },
};
Loading
Loading