diff --git a/src/widgets/glances/components/block.test.jsx b/src/widgets/glances/components/block.test.jsx new file mode 100644 index 000000000..5a2835975 --- /dev/null +++ b/src/widgets/glances/components/block.test.jsx @@ -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( + +
hi
+
, + ); + + const el = screen.getByText("hi").parentElement; + expect(el).toHaveClass("absolute"); + expect(el).toHaveClass("top-1"); + expect(el).toHaveClass("left-2"); + }); +}); diff --git a/src/widgets/glances/components/chart.test.jsx b/src/widgets/glances/components/chart.test.jsx new file mode 100644 index 000000000..9d0d2ee40 --- /dev/null +++ b/src/widgets/glances/components/chart.test.jsx @@ -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 }) =>
{children}
, + 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
{kept}
; + }, + Area: ({ name, dataKey }) =>
, + Tooltip: ({ content }) =>
{content}
, +})); + +import Chart from "./chart"; + +describe("widgets/glances/components/chart", () => { + it("renders a single-series chart scaffold", () => { + render( 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(); + }); +}); diff --git a/src/widgets/glances/components/chart_dual.test.jsx b/src/widgets/glances/components/chart_dual.test.jsx new file mode 100644 index 000000000..c914d67cb --- /dev/null +++ b/src/widgets/glances/components/chart_dual.test.jsx @@ -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 }) =>
{children}
, + AreaChart: ({ children, stackOffset }) => ( +
+ { + // Filter out raw SVG elements (defs/linearGradient/stop) so jsdom doesn't warn. + React.Children.toArray(children).filter((child) => typeof child?.type === "function") + } +
+ ), + Area: ({ name, dataKey }) =>
, + Tooltip: ({ content }) =>
{content}
, +})); + +import ChartDual from "./chart_dual"; + +describe("widgets/glances/components/chart_dual", () => { + it("renders a dual-series chart scaffold", () => { + render( + 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"); + }); +}); diff --git a/src/widgets/glances/components/container.test.jsx b/src/widgets/glances/components/container.test.jsx new file mode 100644 index 000000000..f3cf5209b --- /dev/null +++ b/src/widgets/glances/components/container.test.jsx @@ -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( + +
child
+
, + { 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(, { + settings: { hideErrors: true }, + }); + expect(container.firstChild).toBeNull(); + }); + + it("renders the error message when error is present and errors are not hidden", () => { + renderWithProviders(, { + settings: { hideErrors: false }, + }); + expect(screen.getByText("widget.api_error")).toBeInTheDocument(); + }); +}); diff --git a/src/widgets/glances/components/custom_tooltip.test.jsx b/src/widgets/glances/components/custom_tooltip.test.jsx new file mode 100644 index 000000000..ea1144d79 --- /dev/null +++ b/src/widgets/glances/components/custom_tooltip.test.jsx @@ -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( String(v)} />); + expect(container.firstChild).toBeNull(); + }); + + it("renders formatted values and series names when active", () => { + render( + `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(); + }); +}); diff --git a/src/widgets/glances/components/error.test.jsx b/src/widgets/glances/components/error.test.jsx new file mode 100644 index 000000000..7cdd4817a --- /dev/null +++ b/src/widgets/glances/components/error.test.jsx @@ -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(); + expect(screen.getByText("widget.api_error")).toBeInTheDocument(); + }); +}); diff --git a/src/widgets/glances/metrics/containers.test.jsx b/src/widgets/glances/metrics/containers.test.jsx new file mode 100644 index 000000000..b3a8dbeb4 --- /dev/null +++ b/src/widgets/glances/metrics/containers.test.jsx @@ -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: () => })); + +import Component from "./containers"; + +describe("widgets/glances/metrics/containers", () => { + it("renders a placeholder while loading", () => { + useWidgetAPI.mockReturnValue({ data: undefined, error: undefined }); + renderWithProviders(, { + settings: { hideErrors: false }, + }); + expect(screen.getByText("-")).toBeInTheDocument(); + }); +}); diff --git a/src/widgets/glances/metrics/cpu.test.jsx b/src/widgets/glances/metrics/cpu.test.jsx new file mode 100644 index 000000000..4ef48a7b8 --- /dev/null +++ b/src/widgets/glances/metrics/cpu.test.jsx @@ -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(, { + settings: { hideErrors: false }, + }); + expect(screen.getByText("-")).toBeInTheDocument(); + }); +}); diff --git a/src/widgets/glances/metrics/disk.test.jsx b/src/widgets/glances/metrics/disk.test.jsx new file mode 100644 index 000000000..f240af912 --- /dev/null +++ b/src/widgets/glances/metrics/disk.test.jsx @@ -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( + , + { + settings: { hideErrors: false }, + }, + ); + expect(screen.getByText("-")).toBeInTheDocument(); + }); +}); diff --git a/src/widgets/glances/metrics/fs.test.jsx b/src/widgets/glances/metrics/fs.test.jsx new file mode 100644 index 000000000..661349e04 --- /dev/null +++ b/src/widgets/glances/metrics/fs.test.jsx @@ -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( + , + { + settings: { hideErrors: false }, + }, + ); + expect(screen.getByText("-")).toBeInTheDocument(); + }); +}); diff --git a/src/widgets/glances/metrics/gpu.test.jsx b/src/widgets/glances/metrics/gpu.test.jsx new file mode 100644 index 000000000..8cb2d8cc4 --- /dev/null +++ b/src/widgets/glances/metrics/gpu.test.jsx @@ -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( + , + { + settings: { hideErrors: false }, + }, + ); + expect(screen.getByText("-")).toBeInTheDocument(); + }); +}); diff --git a/src/widgets/glances/metrics/info.test.jsx b/src/widgets/glances/metrics/info.test.jsx new file mode 100644 index 000000000..51a33f8e5 --- /dev/null +++ b/src/widgets/glances/metrics/info.test.jsx @@ -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(, { + settings: { hideErrors: false }, + }); + expect(document.querySelector(".service-container")).toBeTruthy(); + }); +}); diff --git a/src/widgets/glances/metrics/memory.test.jsx b/src/widgets/glances/metrics/memory.test.jsx new file mode 100644 index 000000000..9b94cbaad --- /dev/null +++ b/src/widgets/glances/metrics/memory.test.jsx @@ -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(, { + settings: { hideErrors: false }, + }); + expect(screen.getByText("-")).toBeInTheDocument(); + }); +}); diff --git a/src/widgets/glances/metrics/net.test.jsx b/src/widgets/glances/metrics/net.test.jsx new file mode 100644 index 000000000..9ed25586d --- /dev/null +++ b/src/widgets/glances/metrics/net.test.jsx @@ -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( + , + { settings: { hideErrors: false } }, + ); + expect(screen.getByText("-")).toBeInTheDocument(); + }); +}); diff --git a/src/widgets/glances/metrics/process.test.jsx b/src/widgets/glances/metrics/process.test.jsx new file mode 100644 index 000000000..9a3ded419 --- /dev/null +++ b/src/widgets/glances/metrics/process.test.jsx @@ -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: () => })); + +import Component from "./process"; + +describe("widgets/glances/metrics/process", () => { + it("renders a placeholder while loading", () => { + useWidgetAPI.mockReturnValue({ data: undefined, error: undefined }); + renderWithProviders(, { + settings: { hideErrors: false }, + }); + expect(screen.getByText("-")).toBeInTheDocument(); + }); +}); diff --git a/src/widgets/glances/metrics/sensor.test.jsx b/src/widgets/glances/metrics/sensor.test.jsx new file mode 100644 index 000000000..4dee7a9cb --- /dev/null +++ b/src/widgets/glances/metrics/sensor.test.jsx @@ -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( + , + { + settings: { hideErrors: false }, + }, + ); + expect(screen.getByText("-")).toBeInTheDocument(); + }); +});