diff --git a/internal/site/src/lib/network-monitor-utils.ts b/internal/site/src/lib/network-monitor-utils.ts index 4f4e49f6c..dcbf2dffc 100644 --- a/internal/site/src/lib/network-monitor-utils.ts +++ b/internal/site/src/lib/network-monitor-utils.ts @@ -1,12 +1,16 @@ import type { MonitorCertInfo, MonitorStats, NetworkMonitorRecord, RawMonitorStatsRecord } from "@/types" +import { toFixedFloat } from "./utils" /** Derive chart metrics from the counts and response sum stored at every retention tier. */ export function getMonitorStats(record: RawMonitorStatsRecord): MonitorStats { return { - res_avg: record.success_count > 0 ? record.res_sum / record.success_count : 0, + res_avg: record.success_count > 0 ? toFixedFloat(record.res_sum / record.success_count, 2) : 0, res_min: record.res_min, res_max: record.res_max, - loss: record.total_count > 0 ? ((record.total_count - record.success_count) / record.total_count) * 100 : 0, + loss: + record.total_count > 0 + ? toFixedFloat(((record.total_count - record.success_count) / record.total_count) * 100, 2) + : 0, } } diff --git a/internal/site/src/lib/utils.ts b/internal/site/src/lib/utils.ts index f9050c4c5..4860c7060 100644 --- a/internal/site/src/lib/utils.ts +++ b/internal/site/src/lib/utils.ts @@ -111,18 +111,17 @@ export const updateFavicon = (() => { - ${ - downCount > 0 && - ` + ${downCount > 0 && + ` ${downCount} ` - } + } ` const blob = new Blob([svg], { type: "image/svg+xml" }) const url = URL.createObjectURL(blob) - ;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = url + ; (document.querySelector("link[rel='icon']") as HTMLLinkElement).href = url } })() diff --git a/internal/site/tests/network-monitor-utils.test.ts b/internal/site/tests/network-monitor-utils.test.ts index 80aeec4fa..f58dd38eb 100644 --- a/internal/site/tests/network-monitor-utils.test.ts +++ b/internal/site/tests/network-monitor-utils.test.ts @@ -1,5 +1,11 @@ -import { describe, expect, test } from "bun:test" -import { getMonitorStats } from "../src/lib/network-monitor-utils" +import { describe, expect, mock, test } from "bun:test" + +mock.module("@lingui/core/macro", () => ({ + t: (strings: string | TemplateStringsArray) => (typeof strings === "string" ? strings : (strings?.[0] ?? "")), + plural: (_count: number, forms: { other?: string }) => forms.other ?? "", +})) + +const { getMonitorStats } = await import("../src/lib/network-monitor-utils") describe("monitor stats derived from stored counts", () => { test("retains probe weights and response precision", () => { @@ -12,12 +18,26 @@ describe("monitor stats derived from stored counts", () => { success_count: 6, res_sum: 61, }) - expect(stats.res_avg).toBeCloseTo(10.1666667) - expect(stats.loss).toBeCloseTo(14.2857143) + expect(stats.res_avg).toBe(10.17) + expect(stats.loss).toBe(14.29) expect(stats.res_min).toBe(5) expect(stats.res_max).toBe(20) }) + test("limits average response and loss to two decimals", () => { + const stats = getMonitorStats({ + monitor: "monitor1", + created: 1000, + res_min: 3, + res_max: 4, + total_count: 9, + success_count: 3, + res_sum: 10, + }) + expect(stats.res_avg).toBe(3.33) + expect(stats.loss).toBe(66.67) + }) + test.each([ { total_count: 3, success_count: 0, loss: 100 }, { total_count: 0, success_count: 0, loss: 0 },