mirror of
https://github.com/gethomepage/homepage.git
synced 2026-02-07 16:30:52 +08:00
test: add info widget component tests
This commit is contained in:
32
src/components/widgets/datetime/datetime.test.jsx
Normal file
32
src/components/widgets/datetime/datetime.test.jsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { screen } from "@testing-library/react";
|
||||||
|
import { describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { renderWithProviders } from "test-utils/render-with-providers";
|
||||||
|
|
||||||
|
import DateTime from "./datetime";
|
||||||
|
|
||||||
|
describe("components/widgets/datetime", () => {
|
||||||
|
it("renders formatted date/time and updates on an interval", async () => {
|
||||||
|
vi.useFakeTimers();
|
||||||
|
try {
|
||||||
|
vi.setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
|
||||||
|
|
||||||
|
const format = { timeZone: "UTC", hour: "2-digit", minute: "2-digit", second: "2-digit" };
|
||||||
|
const expected0 = new Intl.DateTimeFormat("en-US", format).format(new Date());
|
||||||
|
|
||||||
|
renderWithProviders(<DateTime options={{ locale: "en-US", format }} />, { settings: { target: "_self" } });
|
||||||
|
|
||||||
|
// `render` wraps in `act`, so effects should flush synchronously.
|
||||||
|
expect(screen.getByText(expected0)).toBeInTheDocument();
|
||||||
|
|
||||||
|
await vi.advanceTimersByTimeAsync(1000);
|
||||||
|
const expected1 = new Intl.DateTimeFormat("en-US", format).format(new Date());
|
||||||
|
|
||||||
|
expect(screen.getByText(expected1)).toBeInTheDocument();
|
||||||
|
} finally {
|
||||||
|
vi.useRealTimers();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
51
src/components/widgets/glances/glances.test.jsx
Normal file
51
src/components/widgets/glances/glances.test.jsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { screen } from "@testing-library/react";
|
||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { renderWithProviders } from "test-utils/render-with-providers";
|
||||||
|
|
||||||
|
const { useSWR } = vi.hoisted(() => ({ useSWR: vi.fn() }));
|
||||||
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
|
|
||||||
|
import Glances from "./glances";
|
||||||
|
|
||||||
|
describe("components/widgets/glances", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders placeholder resources while loading", () => {
|
||||||
|
useSWR.mockReturnValue({ data: undefined, error: undefined });
|
||||||
|
|
||||||
|
renderWithProviders(<Glances options={{ cpu: true, mem: true, cputemp: true, disk: "/", uptime: true }} />, {
|
||||||
|
settings: { target: "_self" },
|
||||||
|
});
|
||||||
|
|
||||||
|
// All placeholders use glances.wait.
|
||||||
|
expect(screen.getAllByText("glances.wait").length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders cpu percent and memory available when data is present", () => {
|
||||||
|
useSWR.mockReturnValue({
|
||||||
|
data: {
|
||||||
|
cpu: { total: 12.34 },
|
||||||
|
load: { min15: 5 },
|
||||||
|
mem: { available: 1024, total: 2048, percent: 50 },
|
||||||
|
fs: [{ mnt_point: "/", free: 100, size: 200, percent: 50 }],
|
||||||
|
sensors: [],
|
||||||
|
uptime: "1 days, 00:00:00",
|
||||||
|
},
|
||||||
|
error: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
renderWithProviders(<Glances options={{ cpu: true, mem: true, disk: "/", uptime: true }} />, {
|
||||||
|
settings: { target: "_self" },
|
||||||
|
});
|
||||||
|
|
||||||
|
// common.number is mocked to return the numeric value as a string.
|
||||||
|
expect(screen.getByText("12.34")).toBeInTheDocument();
|
||||||
|
// common.bytes is mocked similarly; we just assert the numeric value is present.
|
||||||
|
expect(screen.getByText("1024")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
20
src/components/widgets/greeting/greeting.test.jsx
Normal file
20
src/components/widgets/greeting/greeting.test.jsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { screen } from "@testing-library/react";
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { renderWithProviders } from "test-utils/render-with-providers";
|
||||||
|
|
||||||
|
import Greeting from "./greeting";
|
||||||
|
|
||||||
|
describe("components/widgets/greeting", () => {
|
||||||
|
it("renders nothing when text is not configured", () => {
|
||||||
|
const { container } = renderWithProviders(<Greeting options={{}} />, { settings: { target: "_self" } });
|
||||||
|
expect(container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders configured greeting text", () => {
|
||||||
|
renderWithProviders(<Greeting options={{ text: "Hello there" }} />, { settings: { target: "_self" } });
|
||||||
|
expect(screen.getByText("Hello there")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
45
src/components/widgets/kubernetes/kubernetes.test.jsx
Normal file
45
src/components/widgets/kubernetes/kubernetes.test.jsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { screen } from "@testing-library/react";
|
||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { renderWithProviders } from "test-utils/render-with-providers";
|
||||||
|
|
||||||
|
const { useSWR } = vi.hoisted(() => ({ useSWR: vi.fn() }));
|
||||||
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
|
|
||||||
|
vi.mock("./node", () => ({
|
||||||
|
default: ({ type }) => <div data-testid="kube-node" data-type={type} />,
|
||||||
|
}));
|
||||||
|
|
||||||
|
import Kubernetes from "./kubernetes";
|
||||||
|
|
||||||
|
describe("components/widgets/kubernetes", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders placeholder nodes while loading", () => {
|
||||||
|
useSWR.mockReturnValue({ data: undefined, error: undefined });
|
||||||
|
|
||||||
|
renderWithProviders(<Kubernetes options={{ cluster: { show: true }, nodes: { show: true } }} />, {
|
||||||
|
settings: { target: "_self" },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getAllByTestId("kube-node").map((n) => n.getAttribute("data-type"))).toEqual(["cluster", "node"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders a node per returned entry when data is available", () => {
|
||||||
|
useSWR.mockReturnValue({
|
||||||
|
data: { cluster: {}, nodes: [{ name: "n1" }, { name: "n2" }] },
|
||||||
|
error: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
renderWithProviders(<Kubernetes options={{ cluster: { show: true }, nodes: { show: true } }} />, {
|
||||||
|
settings: { target: "_self" },
|
||||||
|
});
|
||||||
|
|
||||||
|
// cluster + 2 nodes
|
||||||
|
expect(screen.getAllByTestId("kube-node")).toHaveLength(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
26
src/components/widgets/logo/logo.test.jsx
Normal file
26
src/components/widgets/logo/logo.test.jsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// @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("components/resolvedicon", () => ({
|
||||||
|
default: ({ icon }) => <div data-testid="resolved-icon" data-icon={icon} />,
|
||||||
|
}));
|
||||||
|
|
||||||
|
import Logo from "./logo";
|
||||||
|
|
||||||
|
describe("components/widgets/logo", () => {
|
||||||
|
it("renders a fallback SVG when no icon is configured", () => {
|
||||||
|
const { container } = renderWithProviders(<Logo options={{}} />, { settings: { target: "_self" } });
|
||||||
|
expect(screen.queryByTestId("resolved-icon")).toBeNull();
|
||||||
|
expect(container.querySelector("svg")).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders the configured icon via ResolvedIcon", () => {
|
||||||
|
renderWithProviders(<Logo options={{ icon: "mdi:home" }} />, { settings: { target: "_self" } });
|
||||||
|
const icon = screen.getByTestId("resolved-icon");
|
||||||
|
expect(icon.getAttribute("data-icon")).toBe("mdi:home");
|
||||||
|
});
|
||||||
|
});
|
||||||
50
src/components/widgets/longhorn/longhorn.test.jsx
Normal file
50
src/components/widgets/longhorn/longhorn.test.jsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { screen } from "@testing-library/react";
|
||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { renderWithProviders } from "test-utils/render-with-providers";
|
||||||
|
|
||||||
|
const { useSWR } = vi.hoisted(() => ({ useSWR: vi.fn() }));
|
||||||
|
|
||||||
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
|
|
||||||
|
vi.mock("./node", () => ({
|
||||||
|
default: ({ data }) => <div data-testid="longhorn-node" data-id={data.node.id} />,
|
||||||
|
}));
|
||||||
|
|
||||||
|
import Longhorn from "./longhorn";
|
||||||
|
|
||||||
|
describe("components/widgets/longhorn", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders an empty container while loading", () => {
|
||||||
|
useSWR.mockReturnValue({ data: undefined, error: undefined });
|
||||||
|
|
||||||
|
const { container } = renderWithProviders(<Longhorn options={{ nodes: true, total: true }} />, {
|
||||||
|
settings: { target: "_self" },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(container.querySelector(".infomation-widget-longhorn")).not.toBeNull();
|
||||||
|
expect(screen.queryAllByTestId("longhorn-node")).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("filters nodes based on options (total/include)", () => {
|
||||||
|
useSWR.mockReturnValue({
|
||||||
|
data: {
|
||||||
|
nodes: [{ id: "total" }, { id: "node1" }, { id: "node2" }],
|
||||||
|
},
|
||||||
|
error: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
renderWithProviders(
|
||||||
|
<Longhorn options={{ nodes: true, total: true, include: ["node1"], expanded: false, labels: false }} />,
|
||||||
|
{ settings: { target: "_self" } },
|
||||||
|
);
|
||||||
|
|
||||||
|
const nodes = screen.getAllByTestId("longhorn-node");
|
||||||
|
expect(nodes.map((n) => n.getAttribute("data-id"))).toEqual(["total", "node1"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
43
src/components/widgets/openmeteo/openmeteo.test.jsx
Normal file
43
src/components/widgets/openmeteo/openmeteo.test.jsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { screen, waitFor } from "@testing-library/react";
|
||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { renderWithProviders } from "test-utils/render-with-providers";
|
||||||
|
|
||||||
|
const { useSWR } = vi.hoisted(() => ({ useSWR: vi.fn() }));
|
||||||
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
|
|
||||||
|
import OpenMeteo from "./openmeteo";
|
||||||
|
|
||||||
|
describe("components/widgets/openmeteo", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders a location prompt when no coordinates are available", () => {
|
||||||
|
renderWithProviders(<OpenMeteo options={{}} />, { settings: { target: "_self" } });
|
||||||
|
|
||||||
|
expect(screen.getByText("weather.current")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("weather.allow")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders temperature and condition when coordinates are provided", async () => {
|
||||||
|
useSWR.mockReturnValue({
|
||||||
|
data: {
|
||||||
|
current_weather: { temperature: 22.2, weathercode: 0, time: "2020-01-01T12:00" },
|
||||||
|
daily: { sunrise: ["2020-01-01T06:00"], sunset: ["2020-01-01T18:00"] },
|
||||||
|
},
|
||||||
|
error: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
renderWithProviders(<OpenMeteo options={{ latitude: 1, longitude: 2, label: "Home", format: {} }} />, {
|
||||||
|
settings: { target: "_self" },
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText("Home, 22.2")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
expect(screen.getByText("wmo.0-day")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
45
src/components/widgets/openweathermap/weather.test.jsx
Normal file
45
src/components/widgets/openweathermap/weather.test.jsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { screen, waitFor } from "@testing-library/react";
|
||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { renderWithProviders } from "test-utils/render-with-providers";
|
||||||
|
|
||||||
|
const { useSWR } = vi.hoisted(() => ({ useSWR: vi.fn() }));
|
||||||
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
|
|
||||||
|
import OpenWeatherMap from "./weather";
|
||||||
|
|
||||||
|
describe("components/widgets/openweathermap", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders a location prompt when no coordinates are available", () => {
|
||||||
|
renderWithProviders(<OpenWeatherMap options={{}} />, { settings: { target: "_self" } });
|
||||||
|
|
||||||
|
expect(screen.getByText("weather.current")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("weather.allow")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders temperature and description when coordinates are provided", async () => {
|
||||||
|
useSWR.mockReturnValue({
|
||||||
|
data: {
|
||||||
|
main: { temp: 71 },
|
||||||
|
weather: [{ id: 800, description: "clear sky" }],
|
||||||
|
dt: 10,
|
||||||
|
sys: { sunrise: 0, sunset: 100 },
|
||||||
|
},
|
||||||
|
error: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
renderWithProviders(<OpenWeatherMap options={{ latitude: 1, longitude: 2, label: "Home", format: {} }} />, {
|
||||||
|
settings: { target: "_self" },
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText("Home, 71")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
expect(screen.getByText("clear sky")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
42
src/components/widgets/resources/resources.test.jsx
Normal file
42
src/components/widgets/resources/resources.test.jsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// @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("./cpu", () => ({ default: () => <div data-testid="resources-cpu" /> }));
|
||||||
|
vi.mock("./memory", () => ({ default: () => <div data-testid="resources-memory" /> }));
|
||||||
|
vi.mock("./disk", () => ({ default: ({ options }) => <div data-testid="resources-disk" data-disk={options.disk} /> }));
|
||||||
|
vi.mock("./network", () => ({ default: () => <div data-testid="resources-network" /> }));
|
||||||
|
vi.mock("./cputemp", () => ({ default: () => <div data-testid="resources-cputemp" /> }));
|
||||||
|
vi.mock("./uptime", () => ({ default: () => <div data-testid="resources-uptime" /> }));
|
||||||
|
|
||||||
|
import Resources from "./resources";
|
||||||
|
|
||||||
|
describe("components/widgets/resources", () => {
|
||||||
|
it("renders selected resource blocks and an optional label", () => {
|
||||||
|
renderWithProviders(
|
||||||
|
<Resources
|
||||||
|
options={{
|
||||||
|
cpu: true,
|
||||||
|
memory: true,
|
||||||
|
disk: ["/", "/data"],
|
||||||
|
network: true,
|
||||||
|
cputemp: true,
|
||||||
|
uptime: true,
|
||||||
|
label: "Host A",
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
{ settings: { target: "_self" } },
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByTestId("resources-cpu")).toBeInTheDocument();
|
||||||
|
expect(screen.getByTestId("resources-memory")).toBeInTheDocument();
|
||||||
|
expect(screen.getAllByTestId("resources-disk")).toHaveLength(2);
|
||||||
|
expect(screen.getByTestId("resources-network")).toBeInTheDocument();
|
||||||
|
expect(screen.getByTestId("resources-cputemp")).toBeInTheDocument();
|
||||||
|
expect(screen.getByTestId("resources-uptime")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("Host A")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
49
src/components/widgets/search/search.test.jsx
Normal file
49
src/components/widgets/search/search.test.jsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { fireEvent, screen } from "@testing-library/react";
|
||||||
|
import { describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { renderWithProviders } from "test-utils/render-with-providers";
|
||||||
|
|
||||||
|
// HeadlessUI is hard to test reliably; stub the primitives to simple pass-through components.
|
||||||
|
vi.mock("@headlessui/react", async () => {
|
||||||
|
const React = await import("react");
|
||||||
|
const { Fragment } = React;
|
||||||
|
|
||||||
|
function passthrough({ as: As = "div", children, ...props }) {
|
||||||
|
if (As === Fragment) return <>{typeof children === "function" ? children({ active: false }) : children}</>;
|
||||||
|
const content = typeof children === "function" ? children({ active: false }) : children;
|
||||||
|
return <As {...props}>{content}</As>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
Combobox: passthrough,
|
||||||
|
ComboboxInput: (props) => <input {...props} />,
|
||||||
|
ComboboxOption: passthrough,
|
||||||
|
ComboboxOptions: passthrough,
|
||||||
|
Listbox: passthrough,
|
||||||
|
ListboxButton: (props) => <button type="button" {...props} />,
|
||||||
|
ListboxOption: passthrough,
|
||||||
|
ListboxOptions: passthrough,
|
||||||
|
Transition: ({ children }) => <>{children}</>,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
import Search from "./search";
|
||||||
|
|
||||||
|
describe("components/widgets/search", () => {
|
||||||
|
it("opens a search URL when Enter is pressed", () => {
|
||||||
|
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
|
||||||
|
|
||||||
|
renderWithProviders(<Search options={{ provider: ["google"], showSearchSuggestions: false, target: "_self" }} />, {
|
||||||
|
settings: { target: "_blank" },
|
||||||
|
});
|
||||||
|
|
||||||
|
const input = screen.getByPlaceholderText("search.placeholder");
|
||||||
|
fireEvent.change(input, { target: { value: "hello world" } });
|
||||||
|
fireEvent.keyDown(input, { key: "Enter" });
|
||||||
|
|
||||||
|
expect(openSpy).toHaveBeenCalledWith("https://www.google.com/search?q=hello%20world", "_self");
|
||||||
|
openSpy.mockRestore();
|
||||||
|
});
|
||||||
|
});
|
||||||
46
src/components/widgets/stocks/stocks.test.jsx
Normal file
46
src/components/widgets/stocks/stocks.test.jsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { fireEvent, screen } from "@testing-library/react";
|
||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
import { renderWithProviders } from "test-utils/render-with-providers";
|
||||||
|
|
||||||
|
const { useSWR } = vi.hoisted(() => ({ useSWR: vi.fn() }));
|
||||||
|
vi.mock("swr", () => ({ default: useSWR }));
|
||||||
|
|
||||||
|
import Stocks from "./stocks";
|
||||||
|
|
||||||
|
describe("components/widgets/stocks", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders a loading state while waiting for data", () => {
|
||||||
|
useSWR.mockReturnValue({ data: undefined, error: undefined });
|
||||||
|
|
||||||
|
renderWithProviders(<Stocks options={{}} />, { settings: { target: "_self" } });
|
||||||
|
|
||||||
|
expect(screen.getByText(/stocks\.loading/)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("toggles between price and percent change on click", () => {
|
||||||
|
useSWR.mockReturnValue({
|
||||||
|
data: {
|
||||||
|
stocks: [
|
||||||
|
{ ticker: "NASDAQ:AAPL", currentPrice: 123.45, percentChange: 1.23 },
|
||||||
|
{ ticker: "MSFT", currentPrice: 99.99, percentChange: -0.5 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
error: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
renderWithProviders(<Stocks options={{ color: false }} />, { settings: { target: "_self" } });
|
||||||
|
|
||||||
|
expect(screen.getByText("AAPL")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("123.45")).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole("button"));
|
||||||
|
expect(screen.getByText("1.23%")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("-0.5%")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
59
src/components/widgets/unifi_console/unifi_console.test.jsx
Normal file
59
src/components/widgets/unifi_console/unifi_console.test.jsx
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// @vitest-environment jsdom
|
||||||
|
|
||||||
|
import { screen } from "@testing-library/react";
|
||||||
|
import { beforeEach, 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 UnifiConsole from "./unifi_console";
|
||||||
|
|
||||||
|
describe("components/widgets/unifi_console", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders a wait state when no site is available yet", () => {
|
||||||
|
useWidgetAPI.mockReturnValue({ data: undefined, error: undefined });
|
||||||
|
|
||||||
|
renderWithProviders(<UnifiConsole options={{ index: 0 }} />, { settings: { target: "_self" } });
|
||||||
|
|
||||||
|
expect(screen.getByText("unifi.wait")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders site name and uptime when data is available", () => {
|
||||||
|
useWidgetAPI.mockReturnValue({
|
||||||
|
data: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
name: "default",
|
||||||
|
desc: "Home",
|
||||||
|
health: [
|
||||||
|
{
|
||||||
|
subsystem: "wan",
|
||||||
|
status: "ok",
|
||||||
|
gw_name: "Router",
|
||||||
|
"gw_system-stats": { uptime: 172800 },
|
||||||
|
},
|
||||||
|
{ subsystem: "lan", status: "unknown" },
|
||||||
|
{ subsystem: "wlan", status: "unknown" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
error: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
renderWithProviders(<UnifiConsole options={{ index: 0 }} />, { settings: { target: "_self" } });
|
||||||
|
|
||||||
|
expect(screen.getByText("Router")).toBeInTheDocument();
|
||||||
|
// common.number is mocked to return the numeric value as a string.
|
||||||
|
expect(screen.getByText("2")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("unifi.days")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user