Files
nxdns/web/src/features/live/LiveLogPage.test.tsx
T

81 lines
2.6 KiB
TypeScript

import { act, fireEvent, render, screen } from "@testing-library/react";
import type { LiveQueryEvent } from "@/lib/types";
import { FakeEventSource } from "./fakeEventSource";
import LiveLogPage from "./LiveLogPage";
function frame(ts: number, domain: string, overrides: Partial<LiveQueryEvent> = {}): { data: string } {
const payload: LiveQueryEvent = {
ts,
domain,
client_ip: "192.0.2.10",
qtype: 1,
blocked: false,
block_reason: "",
response_time_us: 500,
cache_hit: true,
upstream: "",
...overrides,
};
return { data: JSON.stringify(payload) };
}
function renderPage() {
const sources: FakeEventSource[] = [];
const createEventSource = (url: string) => {
const es = new FakeEventSource(url);
sources.push(es);
return es;
};
render(<LiveLogPage createEventSource={createEventSource} />);
return sources;
}
test("streams rows, flags blocked ones, and freezes the display", () => {
const sources = renderPage();
expect(screen.getByText("Connecting…")).toBeTruthy();
act(() => sources[0]!.emit("open"));
expect(screen.getByRole("status", { name: "Live" })).toBeTruthy();
expect(screen.getByText("Waiting for queries…")).toBeTruthy();
act(() => {
sources[0]!.emit("query", frame(1000, "ok.example"));
sources[0]!.emit(
"query",
frame(1001, "ads.example", { blocked: true, block_reason: "blocklist:stevenblack", qtype: 28 }),
);
});
expect(screen.getByText("ok.example")).toBeTruthy();
expect(screen.getByText("Blocked")).toBeTruthy();
expect(screen.getByText("blocklist:stevenblack")).toBeTruthy();
expect(screen.getByText("AAAA")).toBeTruthy();
const blockedRow = screen.getByText("ads.example").closest("tr");
expect(blockedRow?.className).toContain("bg-red-50");
const freeze = screen.getByRole("button", { name: "Freeze" });
fireEvent.click(freeze);
expect(freeze.getAttribute("aria-pressed")).toBe("true");
act(() => sources[0]!.emit("query", frame(1002, "later.example")));
expect(screen.queryByText("later.example")).toBeNull();
expect(screen.getByText(/3 in buffer/)).toBeTruthy();
fireEvent.click(screen.getByRole("button", { name: "Resume" }));
expect(screen.getByText("later.example")).toBeTruthy();
});
test("repeated connection failures show the viewer-cap state with a retry button", () => {
const sources = renderPage();
act(() => {
sources[0]!.emit("error");
sources[0]!.emit("error");
sources[0]!.emit("error");
});
expect(screen.getByRole("alert").textContent).toContain("too many live viewers");
fireEvent.click(screen.getByRole("button", { name: "Retry" }));
expect(sources).toHaveLength(2);
expect(screen.getByText("Connecting…")).toBeTruthy();
});