mirror of
https://github.com/Buriburizaem0n/nezha-dash-v1.git
synced 2026-09-19 09:40:14 +00:00
test: add unit tests for various components and utilities
- Created tests for formatBytes function to ensure correct formatting of byte values. - Implemented tests for InjectContext to validate resource injection and cleanup. - Added tests for logo-class helpers to verify platform alias mappings. - Developed tests for nezha-api functions to check API response handling. - Introduced tests for static geographic data to validate country coordinates and GeoJSON structure. - Created comprehensive tests for utility functions including date formatting and public note parsing. - Added tests for Server page to ensure correct rendering and functionality. - Implemented tests for simple pages including error handling and navigation. - Set up testing environment with Vitest and configured coverage reporting.
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
import { QueryClientProvider } from "@tanstack/react-query";
|
||||
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { MemoryRouter, useLocation } from "react-router-dom";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import Footer from "@/components/Footer";
|
||||
import GroupSwitch from "@/components/GroupSwitch";
|
||||
import {
|
||||
ServerDetailChartLoading,
|
||||
ServerDetailLoading,
|
||||
} from "@/components/loading/ServerDetailLoading";
|
||||
import TabSwitch from "@/components/TabSwitch";
|
||||
import { createTestQueryClient, renderWithProviders } from "@/test/utils";
|
||||
|
||||
const apiMocks = vi.hoisted(() => ({
|
||||
fetchSetting: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/nezha-api", () => apiMocks);
|
||||
|
||||
function LocationProbe() {
|
||||
const location = useLocation();
|
||||
return <p>{location.pathname}</p>;
|
||||
}
|
||||
|
||||
describe("Footer", () => {
|
||||
beforeEach(() => {
|
||||
apiMocks.fetchSetting.mockResolvedValue({
|
||||
success: true,
|
||||
data: {
|
||||
config: {
|
||||
debug: false,
|
||||
language: "en-US",
|
||||
site_name: "Nezha",
|
||||
user_template: "",
|
||||
admin_template: "",
|
||||
custom_code: "",
|
||||
},
|
||||
version: "9.9.9",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("renders setting version and project attribution", async () => {
|
||||
renderWithProviders(<Footer />);
|
||||
|
||||
expect(screen.getByText("footer.themeBy")).toBeInTheDocument();
|
||||
expect(screen.getByText("nezha-dash")).toHaveAttribute(
|
||||
"href",
|
||||
"https://github.com/hamster1963/nezha-dash",
|
||||
);
|
||||
expect(await screen.findByText("9.9.9")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Tab and group switches", () => {
|
||||
it("switches tabs and marks the active tab", async () => {
|
||||
const user = userEvent.setup();
|
||||
const setCurrentTab = vi.fn();
|
||||
|
||||
render(
|
||||
<TabSwitch
|
||||
tabs={["Detail", "Network"]}
|
||||
currentTab="Detail"
|
||||
setCurrentTab={setCurrentTab}
|
||||
/>,
|
||||
);
|
||||
|
||||
await user.click(screen.getByText("tabSwitch.Network"));
|
||||
|
||||
expect(setCurrentTab).toHaveBeenCalledWith("Network");
|
||||
expect(
|
||||
screen.getByText("tabSwitch.Detail").parentElement?.parentElement,
|
||||
).toHaveClass("text-black");
|
||||
});
|
||||
|
||||
it("restores saved groups and hides itself when only All exists", async () => {
|
||||
const setCurrentTab = vi.fn();
|
||||
sessionStorage.setItem("selectedGroup", "Edge");
|
||||
|
||||
const { container, rerender } = render(
|
||||
<GroupSwitch
|
||||
tabs={["All", "Edge", "Asia"]}
|
||||
currentTab="All"
|
||||
setCurrentTab={setCurrentTab}
|
||||
/>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(setCurrentTab).toHaveBeenCalledWith("Edge");
|
||||
});
|
||||
|
||||
rerender(
|
||||
<GroupSwitch
|
||||
tabs={["All"]}
|
||||
currentTab="All"
|
||||
setCurrentTab={setCurrentTab}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(container).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
it("scrolls overflowing group tabs and applies custom background styling", async () => {
|
||||
const user = userEvent.setup();
|
||||
const setCurrentTab = vi.fn();
|
||||
vi.spyOn(HTMLElement.prototype, "scrollWidth", "get").mockReturnValue(320);
|
||||
vi.spyOn(HTMLElement.prototype, "clientWidth", "get").mockReturnValue(120);
|
||||
window.CustomBackgroundImage = "/background.jpg";
|
||||
|
||||
const { container } = render(
|
||||
<GroupSwitch
|
||||
tabs={["All", "Edge", "Asia"]}
|
||||
currentTab="All"
|
||||
setCurrentTab={setCurrentTab}
|
||||
/>,
|
||||
);
|
||||
|
||||
const scrollContainer = container.querySelector(
|
||||
".scrollbar-hidden",
|
||||
) as HTMLElement;
|
||||
|
||||
fireEvent.wheel(scrollContainer, { deltaY: 42 });
|
||||
await user.click(screen.getByText("Asia"));
|
||||
|
||||
expect(scrollContainer.scrollLeft).toBe(42);
|
||||
expect(setCurrentTab).toHaveBeenCalledWith("Asia");
|
||||
expect(
|
||||
container.querySelector(".relative.flex.items-center")?.className,
|
||||
).toContain("bg-stone-100/70");
|
||||
});
|
||||
});
|
||||
|
||||
describe("server detail loading states", () => {
|
||||
it("renders chart skeleton cards", () => {
|
||||
const { container } = render(<ServerDetailChartLoading />);
|
||||
|
||||
expect(container.querySelectorAll(".h-\\[182px\\]")).toHaveLength(6);
|
||||
});
|
||||
|
||||
it("navigates home from the detail loading back affordance", async () => {
|
||||
const user = userEvent.setup();
|
||||
const queryClient = createTestQueryClient();
|
||||
|
||||
render(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<MemoryRouter initialEntries={["/server/7"]}>
|
||||
<ServerDetailLoading />
|
||||
<LocationProbe />
|
||||
</MemoryRouter>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
|
||||
await user.click(screen.getAllByAltText("BackIcon")[0]);
|
||||
|
||||
expect(screen.getByText("/")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user