Files
siftlode/frontend/src/modules/settings/MyLogViewer.dom.test.tsx
T
peter be6bd586d7 fix(filters): a pick that hides More… keeps the focus, counts read alike, Plex facets say they failed
Picking in the year dialog the one year the chips hid took More… away with the dialog, and the
focus fell to <body>: it now goes to the picked year's chip. A count badge is compact in the UI
language everywhere (a chip read "17200" beside its cell's "17.2K"). While the Plex facets load
or fail, the sections they fill say so instead of vanishing as if the library had none.
2026-11-14 19:32:01 +01:00

111 lines
4.1 KiB
TypeScript

// @vitest-environment jsdom
//
// "Saját napló" shows this tab's own log live, newest first, filters it by level group and
// text, and copies exactly what is filtered (oldest first, one JSON event per line).
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { act, cleanup, fireEvent, render, screen, within } from "@testing-library/react";
import { clear, log, setLevel } from "../../lib/log";
vi.mock("react-i18next", async (importOriginal) => {
const actual = await importOriginal<typeof import("react-i18next")>();
return {
...actual,
useTranslation: () => ({
t: (key: string, opts?: { count?: number }) =>
opts?.count != null ? `${key}:${opts.count}` : key,
i18n: { language: "en" },
}),
};
});
const copied: string[] = [];
vi.mock("../../lib/clipboard", () => ({
copyText: (text: string) => {
copied.push(text);
return Promise.resolve(true);
},
}));
import MyLogViewer from "./MyLogViewer";
beforeEach(() => {
setLevel("DEBUG");
log.info("nav.view", "push feed", { page: "feed" });
log.warn("http.request", "GET /api/feed 503", { status: 503 });
log.debug("ui.click", "click feed-refresh", { control: "feed-refresh" });
});
afterEach(() => {
cleanup();
clear();
setLevel("INFO");
copied.length = 0;
});
const rows = () =>
within(screen.getByTestId("my-log-lines"))
.queryAllByRole("button")
.map((b) => b.textContent);
describe("MyLogViewer", () => {
it("lists the tab's events newest first and follows new ones", async () => {
render(<MyLogViewer />);
expect(rows().map((r) => r!.includes("ui.click"))).toEqual([true, false, false]);
await act(async () => {
log.error("app.uncaught", "TypeError: x is undefined");
await new Promise((r) => requestAnimationFrame(() => r(null)));
});
expect(rows()[0]).toContain("app.uncaught");
});
it("a row keeps its place and the focus as new events arrive above it", async () => {
render(<MyLogViewer />);
const row = within(screen.getByTestId("my-log-lines")).getAllByRole("button")[0]!;
row.focus();
fireEvent.click(row); // at Részletes this click is itself a new event in real use
await act(async () => {
log.debug("ui.click", "a newer event");
await new Promise((r) => requestAnimationFrame(() => r(null)));
});
expect(row.isConnected).toBe(true);
expect(document.activeElement).toBe(row);
expect(row.getAttribute("aria-expanded")).toBe("true");
});
it("filters by level group and by text, and copies only what is shown", async () => {
render(<MyLogViewer />);
fireEvent.click(screen.getByRole("button", { name: /settings\.myLog\.filters\.warning/ }));
expect(rows()).toHaveLength(1);
expect(rows()[0]).toContain("GET /api/feed 503");
fireEvent.click(screen.getByRole("button", { name: /settings\.myLog\.filters\.all/ }));
fireEvent.change(screen.getByRole("searchbox"), { target: { value: "FEED-REFRESH" } });
expect(rows()).toHaveLength(1);
const copy = async () => {
await act(async () => {
fireEvent.click(screen.getByRole("button", { name: "settings.myLog.copy" }));
});
return copied[copied.length - 1]!.split("\n").map((l) => JSON.parse(l).event);
};
expect(await copy()).toEqual(["ui.click"]); // only what the search left
fireEvent.change(screen.getByRole("searchbox"), { target: { value: "" } });
expect(await copy()).toEqual(["nav.view", "http.request", "ui.click"]); // oldest first
});
it("opens a row to its details and clears the log", async () => {
render(<MyLogViewer />);
const first = within(screen.getByTestId("my-log-lines")).getAllByRole("button")[0]!;
fireEvent.click(first);
expect(first.getAttribute("aria-expanded")).toBe("true");
expect(screen.getByTestId("my-log-lines").textContent).toContain('"control": "feed-refresh"');
await act(async () => {
fireEvent.click(screen.getByRole("button", { name: "settings.myLog.clear" }));
await new Promise((r) => requestAnimationFrame(() => r(null)));
});
expect(rows()).toEqual([]);
expect(screen.getByText("settings.myLog.emptyAll")).toBeTruthy();
});
});