import { afterEach, describe, expect, it, vi } from "vitest"; import { cleanup, fireEvent, render, screen, waitFor, within, } from "@testing-library/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { Refine } from "@refinedev/core"; import { MemoryRouter } from "react-router"; import { GatewayList } from "./GatewaysPage"; afterEach(() => { cleanup(); vi.restoreAllMocks(); }); const gateways = [ { id: "gw-1", name: "gw-1", endpoint: "http://docker-gateway:8081", token: "unit-test-gateway-token", connectivity: "online", health: "healthy", }, { id: "gw-2", name: "gw-2", endpoint: "http://gw2:8081", token: "offline-token-123456", connectivity: "offline", connectivity_reason: "connection refused", health: "unhealthy", health_reason: "gateway unreachable", }, ]; function provider(overrides = {}) { return { getList: vi.fn(() => Promise.resolve({ data: gateways, total: gateways.length }), ), create: vi .fn() .mockResolvedValue({ data: { name: "gw-2", endpoint: "http://gw2:8081", token: "generated-token-abcdef", }, }), deleteOne: vi.fn().mockResolvedValue({ data: { id: "gw-1" } }), getOne: vi.fn(), getMany: vi.fn(), getManyReference: vi.fn(), update: vi.fn(), updateMany: vi.fn(), deleteMany: vi.fn(), browserAction: vi.fn(), ...overrides, }; } const renderGateways = (dataProvider) => render( , ); describe("GatewayList", () => { it("registers a gateway and reveals the generated token", async () => { const dataProvider = provider(); renderGateways(dataProvider); await screen.findAllByText("gw-1"); fireEvent.click(screen.getByRole("button", { name: "注册网关" })); const dialog = screen.getByRole("dialog"); fireEvent.change(within(dialog).getByRole("textbox", { name: "名称" }), { target: { value: "gw-2" }, }); fireEvent.change( within(dialog).getByRole("textbox", { name: "Endpoint" }), { target: { value: "http://gw2:8081" } }, ); fireEvent.click(within(dialog).getByRole("button", { name: "注册网关" })); await waitFor(() => expect(dataProvider.create).toHaveBeenCalledWith({ resource: "gateways", variables: { name: "gw-2", endpoint: "http://gw2:8081", token: "" }, }), ); expect((await screen.findByRole("alert")).textContent).toContain( "generated-token-abcdef", ); }); it("rejects an invalid endpoint before submit", async () => { const dataProvider = provider(); renderGateways(dataProvider); await screen.findAllByText("gw-1"); fireEvent.click(screen.getByRole("button", { name: "注册网关" })); const dialog = screen.getByRole("dialog"); fireEvent.change(within(dialog).getByRole("textbox", { name: "名称" }), { target: { value: "gw-2" }, }); fireEvent.change( within(dialog).getByRole("textbox", { name: "Endpoint" }), { target: { value: "ftp://gw2:8081" } }, ); expect( within(dialog).getByRole("button", { name: "注册网关" }).disabled, ).toBe(true); expect(dataProvider.create).not.toHaveBeenCalled(); }); it("deletes a gateway after confirm", async () => { const dataProvider = provider(); renderGateways(dataProvider); fireEvent.click(await screen.findByLabelText("删除 gw-1")); fireEvent.click(await screen.findByRole("button", { name: "确认删除" })); await waitFor(() => expect(dataProvider.deleteOne).toHaveBeenCalledWith({ resource: "gateways", id: "gw-1", }), ); }); it("shows connectivity and health with reasons for failing gateways", async () => { renderGateways(provider()); const online = await screen.findByText("在线"); expect((await screen.findAllByText("健康")).length).toBeGreaterThan(0); const offline = screen.getByText("离线"); const unhealthy = screen.getByText("异常"); expect(offline.closest("[title]")?.getAttribute("title")).toBe( "connection refused", ); expect(unhealthy.closest("[title]")?.getAttribute("title")).toBe( "gateway unreachable", ); expect(online.closest("[title]")).toBe(null); }); });