Chore: homepage tests (#6278)

This commit is contained in:
shamoon
2026-02-04 19:58:39 -08:00
committed by GitHub
parent 7d019185a3
commit 872a3600aa
558 changed files with 32606 additions and 84 deletions

View File

@@ -0,0 +1,59 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
vi.mock("./metrics/info", () => ({ default: () => <div>glances-info</div> }));
vi.mock("./metrics/memory", () => ({ default: () => <div>glances-memory</div> }));
vi.mock("./metrics/process", () => ({ default: () => <div>glances-process</div> }));
vi.mock("./metrics/containers", () => ({ default: () => <div>glances-containers</div> }));
vi.mock("./metrics/cpu", () => ({ default: () => <div>glances-cpu</div> }));
vi.mock("./metrics/net", () => ({ default: () => <div>glances-net</div> }));
vi.mock("./metrics/sensor", () => ({ default: () => <div>glances-sensor</div> }));
vi.mock("./metrics/disk", () => ({ default: () => <div>glances-disk</div> }));
vi.mock("./metrics/gpu", () => ({ default: () => <div>glances-gpu</div> }));
vi.mock("./metrics/fs", () => ({ default: () => <div>glances-fs</div> }));
import Component from "./component";
describe("widgets/glances/component", () => {
it("routes metric=info to Info", () => {
renderWithProviders(<Component service={{ widget: { type: "glances", metric: "info" } }} />, {
settings: { hideErrors: false },
});
expect(screen.getByText("glances-info")).toBeInTheDocument();
});
it("routes metric=cpu to Cpu", () => {
renderWithProviders(<Component service={{ widget: { type: "glances", metric: "cpu" } }} />, {
settings: { hideErrors: false },
});
expect(screen.getByText("glances-cpu")).toBeInTheDocument();
});
it("routes metric patterns (network:, sensor:, disk:, gpu:, fs:) to their modules", () => {
const { rerender } = renderWithProviders(
<Component service={{ widget: { type: "glances", metric: "network:eth0" } }} />,
{
settings: { hideErrors: false },
},
);
expect(screen.getByText("glances-net")).toBeInTheDocument();
rerender(<Component service={{ widget: { type: "glances", metric: "sensor:temp" } }} />);
expect(screen.getByText("glances-sensor")).toBeInTheDocument();
rerender(<Component service={{ widget: { type: "glances", metric: "disk:sda" } }} />);
expect(screen.getByText("glances-disk")).toBeInTheDocument();
rerender(<Component service={{ widget: { type: "glances", metric: "gpu:nvidia" } }} />);
expect(screen.getByText("glances-gpu")).toBeInTheDocument();
rerender(<Component service={{ widget: { type: "glances", metric: "fs:/" } }} />);
expect(screen.getByText("glances-fs")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,21 @@
// @vitest-environment jsdom
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import Block from "./block";
describe("widgets/glances/components/block", () => {
it("renders children with the given absolute position classes", () => {
render(
<Block position="top-1 left-2">
<div>hi</div>
</Block>,
);
const el = screen.getByText("hi").parentElement;
expect(el).toHaveClass("absolute");
expect(el).toHaveClass("top-1");
expect(el).toHaveClass("left-2");
});
});

View File

@@ -0,0 +1,31 @@
// @vitest-environment jsdom
import { render, screen } from "@testing-library/react";
import React from "react";
import { describe, expect, it, vi } from "vitest";
vi.mock("recharts", () => ({
ResponsiveContainer: ({ children }) => <div data-testid="ResponsiveContainer">{children}</div>,
AreaChart: ({ children }) => {
// Filter out raw SVG elements (defs/linearGradient/stop) so jsdom doesn't warn.
const kept = React.Children.toArray(children).filter((child) => typeof child?.type === "function");
return <div data-testid="AreaChart">{kept}</div>;
},
Area: ({ name, dataKey }) => <div data-testid="Area" data-name={name} data-key={dataKey} />,
Tooltip: ({ content }) => <div data-testid="Tooltip">{content}</div>,
}));
import Chart from "./chart";
describe("widgets/glances/components/chart", () => {
it("renders a single-series chart scaffold", () => {
render(<Chart dataPoints={[{ value: 1 }]} formatter={(v) => String(v)} label={["Series"]} />);
expect(screen.getByTestId("ResponsiveContainer")).toBeInTheDocument();
expect(screen.getByTestId("AreaChart")).toBeInTheDocument();
const area = screen.getByTestId("Area");
expect(area).toHaveAttribute("data-name", "Series");
expect(area).toHaveAttribute("data-key", "value");
expect(screen.getByTestId("Tooltip")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,38 @@
// @vitest-environment jsdom
import { render, screen } from "@testing-library/react";
import React from "react";
import { describe, expect, it, vi } from "vitest";
vi.mock("recharts", () => ({
ResponsiveContainer: ({ children }) => <div data-testid="ResponsiveContainer">{children}</div>,
AreaChart: ({ children, stackOffset }) => (
<div data-testid="AreaChart" data-stackoffset={stackOffset ?? ""}>
{
// Filter out raw SVG elements (defs/linearGradient/stop) so jsdom doesn't warn.
React.Children.toArray(children).filter((child) => typeof child?.type === "function")
}
</div>
),
Area: ({ name, dataKey }) => <div data-testid="Area" data-name={name} data-key={dataKey} />,
Tooltip: ({ content }) => <div data-testid="Tooltip">{content}</div>,
}));
import ChartDual from "./chart_dual";
describe("widgets/glances/components/chart_dual", () => {
it("renders a dual-series chart scaffold", () => {
render(
<ChartDual dataPoints={[{ a: 1, b: 2 }]} formatter={(v) => String(v)} label={["A", "B"]} stackOffset="expand" />,
);
expect(screen.getByTestId("ResponsiveContainer")).toBeInTheDocument();
const chart = screen.getByTestId("AreaChart");
expect(chart).toHaveAttribute("data-stackoffset", "expand");
const areas = screen.getAllByTestId("Area");
expect(areas).toHaveLength(2);
expect(areas[0]).toHaveAttribute("data-key", "a");
expect(areas[1]).toHaveAttribute("data-key", "b");
});
});

View File

@@ -0,0 +1,37 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
import Container from "./container";
describe("widgets/glances/components/container", () => {
it("renders children and chart spacing when not in error state", () => {
renderWithProviders(
<Container chart>
<div>child</div>
</Container>,
{ settings: { hideErrors: false } },
);
expect(screen.getByText("child")).toBeInTheDocument();
expect(document.querySelector(".service-container")).toBeTruthy();
expect(document.querySelector(".h-\\[68px\\]")).toBeTruthy();
});
it("renders nothing when error is present and errors are hidden", () => {
const { container } = renderWithProviders(<Container error={{ message: "nope" }} widget={{ hideErrors: true }} />, {
settings: { hideErrors: true },
});
expect(container.firstChild).toBeNull();
});
it("renders the error message when error is present and errors are not hidden", () => {
renderWithProviders(<Container error={{ message: "nope" }} widget={{ hideErrors: false }} />, {
settings: { hideErrors: false },
});
expect(screen.getByText("widget.api_error")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,29 @@
// @vitest-environment jsdom
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import CustomTooltip from "./custom_tooltip";
describe("widgets/glances/components/custom_tooltip", () => {
it("returns null when inactive", () => {
const { container } = render(<CustomTooltip active={false} payload={[]} formatter={(v) => String(v)} />);
expect(container.firstChild).toBeNull();
});
it("renders formatted values and series names when active", () => {
render(
<CustomTooltip
active
formatter={(v) => `v=${v}`}
payload={[
{ value: 1, name: "A" },
{ value: 2, name: "B" },
]}
/>,
);
expect(screen.getByText("v=1 A")).toBeInTheDocument();
expect(screen.getByText("v=2 B")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,13 @@
// @vitest-environment jsdom
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import Error from "./error";
describe("widgets/glances/components/error", () => {
it("renders the standard widget api error message", () => {
render(<Error />);
expect(screen.getByText("widget.api_error")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,24 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
// Avoid pulling Next/Image + ThemeContext requirements into these unit tests.
vi.mock("components/resolvedicon", () => ({ default: () => <span data-testid="resolvedicon" /> }));
import Component from "./containers";
describe("widgets/glances/metrics/containers", () => {
it("renders a placeholder while loading", () => {
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
renderWithProviders(<Component service={{ widget: { chart: false, version: 3 } }} />, {
settings: { hideErrors: false },
});
expect(screen.getByText("-")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,22 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
vi.mock("next/dynamic", () => ({ default: () => () => null }));
import Component from "./cpu";
describe("widgets/glances/metrics/cpu", () => {
it("renders a placeholder while loading", () => {
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
renderWithProviders(<Component service={{ widget: { chart: false, version: 3, pointsLimit: 3 } }} />, {
settings: { hideErrors: false },
});
expect(screen.getByText("-")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,25 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
vi.mock("next/dynamic", () => ({ default: () => () => null }));
import Component from "./disk";
describe("widgets/glances/metrics/disk", () => {
it("renders a placeholder while loading", () => {
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
renderWithProviders(
<Component service={{ widget: { chart: false, version: 3, pointsLimit: 3, metric: "disk:sda" } }} />,
{
settings: { hideErrors: false },
},
);
expect(screen.getByText("-")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,25 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
vi.mock("next/dynamic", () => ({ default: () => () => null }));
import Component from "./fs";
describe("widgets/glances/metrics/fs", () => {
it("renders a placeholder while loading", () => {
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
renderWithProviders(
<Component service={{ widget: { chart: false, version: 3, pointsLimit: 3, metric: "fs:/mnt" } }} />,
{
settings: { hideErrors: false },
},
);
expect(screen.getByText("-")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,25 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
vi.mock("next/dynamic", () => ({ default: () => () => null }));
import Component from "./gpu";
describe("widgets/glances/metrics/gpu", () => {
it("renders a placeholder while loading", () => {
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
renderWithProviders(
<Component service={{ widget: { chart: false, version: 3, pointsLimit: 3, metric: "gpu:gpu0" } }} />,
{
settings: { hideErrors: false },
},
);
expect(screen.getByText("-")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,20 @@
// @vitest-environment jsdom
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
import Component from "./info";
describe("widgets/glances/metrics/info", () => {
it("renders a placeholder while loading", () => {
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
renderWithProviders(<Component service={{ widget: { chart: false, version: 3 } }} />, {
settings: { hideErrors: false },
});
expect(document.querySelector(".service-container")).toBeTruthy();
});
});

View File

@@ -0,0 +1,22 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
vi.mock("next/dynamic", () => ({ default: () => () => null }));
import Component from "./memory";
describe("widgets/glances/metrics/memory", () => {
it("renders a placeholder while loading", () => {
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
renderWithProviders(<Component service={{ widget: { chart: false, version: 3, pointsLimit: 3 } }} />, {
settings: { hideErrors: false },
});
expect(screen.getByText("-")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,23 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
vi.mock("next/dynamic", () => ({ default: () => () => null }));
import Component from "./net";
describe("widgets/glances/metrics/net", () => {
it("renders a placeholder while loading", () => {
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
renderWithProviders(
<Component service={{ widget: { chart: false, version: 3, pointsLimit: 3, metric: "net:eth0" } }} />,
{ settings: { hideErrors: false } },
);
expect(screen.getByText("-")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,22 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
vi.mock("components/resolvedicon", () => ({ default: () => <span data-testid="resolvedicon" /> }));
import Component from "./process";
describe("widgets/glances/metrics/process", () => {
it("renders a placeholder while loading", () => {
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
renderWithProviders(<Component service={{ widget: { chart: false, version: 3 } }} />, {
settings: { hideErrors: false },
});
expect(screen.getByText("-")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,25 @@
// @vitest-environment jsdom
import { screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { renderWithProviders } from "test-utils/render-with-providers";
const { useWidgetAPI } = vi.hoisted(() => ({ useWidgetAPI: vi.fn() }));
vi.mock("utils/proxy/use-widget-api", () => ({ default: useWidgetAPI }));
vi.mock("next/dynamic", () => ({ default: () => () => null }));
import Component from "./sensor";
describe("widgets/glances/metrics/sensor", () => {
it("renders a placeholder while loading", () => {
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
renderWithProviders(
<Component service={{ widget: { chart: false, version: 3, pointsLimit: 3, metric: "sensor:CPU" } }} />,
{
settings: { hideErrors: false },
},
);
expect(screen.getByText("-")).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,13 @@
import { describe, expect, it } from "vitest";
import { expectWidgetConfigShape } from "test-utils/widget-config";
import widget from "./widget";
describe("glances widget config", () => {
it("exports a valid widget config", () => {
expectWidgetConfigShape(widget);
expect(widget.allowedEndpoints?.test("3/quicklook")).toBe(true);
expect(widget.allowedEndpoints?.test("unknown")).toBe(false);
});
});