Files
creator-hub/web/src/GatewaysPage.test.jsx
T
rogee e5c720e7d5 feat(gateways): 网关列表增加连通性与健康状态探测展示
- GET /api/gateways 并发探测 /healthz(连通性)与 /v1/browsers(健康),失败原因随列表返回
- 前端新增连通性/健康两列,失败原因悬浮提示
- 覆盖健康、令牌被拒、离线三类探测路径的单元测试
2026-09-03 12:44:49 +08:00

161 lines
4.5 KiB
React

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(
<QueryClientProvider
client={
new QueryClient({ defaultOptions: { queries: { retry: false } } })
}
>
<Refine dataProvider={dataProvider}>
<MemoryRouter>
<GatewayList />
</MemoryRouter>
</Refine>
</QueryClientProvider>,
);
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);
});
});