From 9039b55b8a8ed47e09878222785dc5fe7375c472 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Wed, 4 Feb 2026 08:13:16 -0800 Subject: [PATCH] test: cover remaining resources widgets + version component --- src/components/version.test.jsx | 67 +++++++++++++++++++ src/components/widgets/resources/cpu.test.jsx | 47 +++++++++++++ .../widgets/resources/cputemp.test.jsx | 45 +++++++++++++ .../widgets/resources/disk.test.jsx | 45 +++++++++++++ .../widgets/resources/memory.test.jsx | 45 +++++++++++++ .../widgets/resources/network.test.jsx | 49 ++++++++++++++ .../widgets/resources/uptime.test.jsx | 46 +++++++++++++ 7 files changed, 344 insertions(+) create mode 100644 src/components/version.test.jsx create mode 100644 src/components/widgets/resources/cpu.test.jsx create mode 100644 src/components/widgets/resources/cputemp.test.jsx create mode 100644 src/components/widgets/resources/disk.test.jsx create mode 100644 src/components/widgets/resources/memory.test.jsx create mode 100644 src/components/widgets/resources/network.test.jsx create mode 100644 src/components/widgets/resources/uptime.test.jsx diff --git a/src/components/version.test.jsx b/src/components/version.test.jsx new file mode 100644 index 000000000..d5576599f --- /dev/null +++ b/src/components/version.test.jsx @@ -0,0 +1,67 @@ +// @vitest-environment jsdom + +import { render, screen } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { cache, cv, useSWR } = vi.hoisted(() => ({ + cache: { + get: vi.fn(), + put: vi.fn(), + }, + cv: { + validate: vi.fn(), + compareVersions: vi.fn(), + }, + useSWR: vi.fn(), +})); + +vi.mock("memory-cache", () => ({ + default: cache, +})); + +vi.mock("compare-versions", () => ({ + validate: cv.validate, + compareVersions: cv.compareVersions, +})); + +vi.mock("swr", () => ({ + default: useSWR, +})); + +import Version from "./version"; + +describe("components/version", () => { + beforeEach(() => { + vi.clearAllMocks(); + process.env.NEXT_PUBLIC_VERSION = "dev"; + process.env.NEXT_PUBLIC_REVISION = "abcdef012345"; + process.env.NEXT_PUBLIC_BUILDTIME = "2020-01-01T00:00:00.000Z"; + }); + + it("renders non-link version text for dev/main/nightly", () => { + cv.validate.mockReturnValue(false); + cache.get.mockReturnValue(null); + useSWR.mockReturnValue({ data: undefined }); + + render(); + + expect(screen.getByText(/dev \(abcdef0/)).toBeInTheDocument(); + expect(screen.queryAllByRole("link")).toHaveLength(0); + }); + + it("renders tag link and shows update available when a newer release exists", () => { + process.env.NEXT_PUBLIC_VERSION = "1.2.3"; + cv.validate.mockReturnValue(true); + cache.get.mockReturnValue(null); + useSWR.mockReturnValue({ + data: [{ tag_name: "1.2.4", html_url: "http://example.com/release" }], + }); + cv.compareVersions.mockReturnValue(1); + + render(); + + const links = screen.getAllByRole("link"); + expect(links.find((a) => a.getAttribute("href")?.includes("/releases/tag/1.2.3"))).toBeTruthy(); + expect(links.find((a) => a.getAttribute("href") === "http://example.com/release")).toBeTruthy(); + }); +}); diff --git a/src/components/widgets/resources/cpu.test.jsx b/src/components/widgets/resources/cpu.test.jsx new file mode 100644 index 000000000..0a2ef019a --- /dev/null +++ b/src/components/widgets/resources/cpu.test.jsx @@ -0,0 +1,47 @@ +// @vitest-environment jsdom + +import { render } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { useSWR, Resource, Error } = vi.hoisted(() => ({ + useSWR: vi.fn(), + Resource: vi.fn(() =>
), + Error: vi.fn(() =>
), +})); + +vi.mock("swr", () => ({ default: useSWR })); +vi.mock("../widget/resource", () => ({ default: Resource })); +vi.mock("../widget/error", () => ({ default: Error })); + +import Cpu from "./cpu"; + +describe("components/widgets/resources/cpu", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("renders a placeholder Resource while loading", () => { + useSWR.mockReturnValue({ data: undefined, error: undefined }); + + render(); + + expect(Resource).toHaveBeenCalled(); + const props = Resource.mock.calls[0][0]; + expect(props.value).toBe("-"); + expect(props.expanded).toBe(true); + }); + + it("renders usage/load values when data is present", () => { + useSWR.mockReturnValue({ + data: { cpu: { usage: 12.3, load: 1.23 } }, + error: undefined, + }); + + render(); + + const props = Resource.mock.calls[0][0]; + expect(props.value).toBe("12.3"); + expect(props.expandedValue).toBe("1.23"); + expect(props.percentage).toBe(12.3); + }); +}); diff --git a/src/components/widgets/resources/cputemp.test.jsx b/src/components/widgets/resources/cputemp.test.jsx new file mode 100644 index 000000000..bbeeb7129 --- /dev/null +++ b/src/components/widgets/resources/cputemp.test.jsx @@ -0,0 +1,45 @@ +// @vitest-environment jsdom + +import { render } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { useSWR, Resource, Error } = vi.hoisted(() => ({ + useSWR: vi.fn(), + Resource: vi.fn(() =>
), + Error: vi.fn(() =>
), +})); + +vi.mock("swr", () => ({ default: useSWR })); +vi.mock("../widget/resource", () => ({ default: Resource })); +vi.mock("../widget/error", () => ({ default: Error })); + +import CpuTemp from "./cputemp"; + +describe("components/widgets/resources/cputemp", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("renders placeholder when temperature data is missing", () => { + useSWR.mockReturnValue({ data: undefined, error: undefined }); + render(); + + const props = Resource.mock.calls[0][0]; + expect(props.value).toBe("-"); + }); + + it("averages core temps, converts to fahrenheit and computes percentage", () => { + useSWR.mockReturnValue({ + data: { cputemp: { main: 10, cores: [10, 10], max: 20 } }, + error: undefined, + }); + + render(); + + const props = Resource.mock.calls[0][0]; + // common.number mock returns string of value + expect(props.value).toBe("50"); + expect(props.expandedValue).toBe("68"); + expect(props.percentage).toBe(74); + }); +}); diff --git a/src/components/widgets/resources/disk.test.jsx b/src/components/widgets/resources/disk.test.jsx new file mode 100644 index 000000000..8065fd870 --- /dev/null +++ b/src/components/widgets/resources/disk.test.jsx @@ -0,0 +1,45 @@ +// @vitest-environment jsdom + +import { render } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { useSWR, Resource, Error } = vi.hoisted(() => ({ + useSWR: vi.fn(), + Resource: vi.fn(() =>
), + Error: vi.fn(() =>
), +})); + +vi.mock("swr", () => ({ default: useSWR })); +vi.mock("../widget/resource", () => ({ default: Resource })); +vi.mock("../widget/error", () => ({ default: Error })); + +import Disk from "./disk"; + +describe("components/widgets/resources/disk", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("renders a placeholder Resource while loading", () => { + useSWR.mockReturnValue({ data: undefined, error: undefined }); + + render(); + + const props = Resource.mock.calls[0][0]; + expect(props.value).toBe("-"); + }); + + it("computes percent used from size/available and renders bytes", () => { + useSWR.mockReturnValue({ + data: { drive: { size: 100, available: 40 } }, + error: undefined, + }); + + render(); + + const props = Resource.mock.calls[0][0]; + expect(props.value).toBe("40"); + expect(props.expandedValue).toBe("100"); + expect(props.percentage).toBe(60); + }); +}); diff --git a/src/components/widgets/resources/memory.test.jsx b/src/components/widgets/resources/memory.test.jsx new file mode 100644 index 000000000..408b2678a --- /dev/null +++ b/src/components/widgets/resources/memory.test.jsx @@ -0,0 +1,45 @@ +// @vitest-environment jsdom + +import { render } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { useSWR, Resource, Error } = vi.hoisted(() => ({ + useSWR: vi.fn(), + Resource: vi.fn(() =>
), + Error: vi.fn(() =>
), +})); + +vi.mock("swr", () => ({ default: useSWR })); +vi.mock("../widget/resource", () => ({ default: Resource })); +vi.mock("../widget/error", () => ({ default: Error })); + +import Memory from "./memory"; + +describe("components/widgets/resources/memory", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("renders a placeholder Resource while loading", () => { + useSWR.mockReturnValue({ data: undefined, error: undefined }); + + render(); + + const props = Resource.mock.calls[0][0]; + expect(props.value).toBe("-"); + }); + + it("calculates percentage from active/total and renders available/total", () => { + useSWR.mockReturnValue({ + data: { memory: { available: 10, total: 20, active: 5 } }, + error: undefined, + }); + + render(); + + const props = Resource.mock.calls[0][0]; + expect(props.value).toBe("10"); + expect(props.expandedValue).toBe("20"); + expect(props.percentage).toBe(25); + }); +}); diff --git a/src/components/widgets/resources/network.test.jsx b/src/components/widgets/resources/network.test.jsx new file mode 100644 index 000000000..83be9428a --- /dev/null +++ b/src/components/widgets/resources/network.test.jsx @@ -0,0 +1,49 @@ +// @vitest-environment jsdom + +import { render } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { useSWR, Resource, Error } = vi.hoisted(() => ({ + useSWR: vi.fn(), + Resource: vi.fn(() =>
), + Error: vi.fn(() =>
), +})); + +vi.mock("swr", () => ({ default: useSWR })); +vi.mock("../widget/resource", () => ({ default: Resource })); +vi.mock("../widget/error", () => ({ default: Error })); + +import Network from "./network"; + +describe("components/widgets/resources/network", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("normalizes options.network=true to default interfaceName in the request", () => { + useSWR.mockReturnValue({ data: undefined, error: undefined }); + + render(); + + expect(useSWR).toHaveBeenCalledWith(expect.stringContaining("interfaceName=default"), expect.any(Object)); + }); + + it("renders rates and usage percentage when data is present", () => { + useSWR.mockReturnValue({ + data: { + network: { rx_sec: 3, tx_sec: 1, rx_bytes: 30, tx_bytes: 10 }, + }, + error: undefined, + }); + + render(); + + const props = Resource.mock.calls[0][0]; + expect(props.value).toContain("1"); + expect(props.value).toContain("↑"); + expect(props.label).toContain("3"); + expect(props.label).toContain("↓"); + expect(props.percentage).toBe(75); + expect(props.wide).toBe(true); + }); +}); diff --git a/src/components/widgets/resources/uptime.test.jsx b/src/components/widgets/resources/uptime.test.jsx new file mode 100644 index 000000000..f99d83bcd --- /dev/null +++ b/src/components/widgets/resources/uptime.test.jsx @@ -0,0 +1,46 @@ +// @vitest-environment jsdom + +import { render } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { useSWR, Resource, Error } = vi.hoisted(() => ({ + useSWR: vi.fn(), + Resource: vi.fn(() =>
), + Error: vi.fn(() =>
), +})); + +vi.mock("swr", () => ({ default: useSWR })); +vi.mock("../widget/resource", () => ({ default: Resource })); +vi.mock("../widget/error", () => ({ default: Error })); + +import Uptime from "./uptime"; + +describe("components/widgets/resources/uptime", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("renders a placeholder while loading", () => { + useSWR.mockReturnValue({ data: undefined, error: undefined }); + + render(); + expect(Resource).toHaveBeenCalled(); + expect(Resource.mock.calls[0][0].value).toBe("-"); + }); + + it("renders formatted duration and sets percentage based on current seconds", () => { + vi.useFakeTimers(); + try { + vi.setSystemTime(new Date("2020-01-01T00:00:30.000Z")); + + useSWR.mockReturnValue({ data: { uptime: 1234 }, error: undefined }); + render(); + + const props = Resource.mock.calls[0][0]; + expect(props.value).toBe("1234"); + expect(props.percentage).toBe("50"); + } finally { + vi.useRealTimers(); + } + }); +});