Files
siftlode/frontend/src/modules/channels/AboutCell.dom.test.tsx
T
peter c910cf2f20 fix: review round 1 — row press after a rename, related reset, dead items on removal, honest Prev/Next
- A press that begins while a field in the row is edited only ends the editing (rowOpen latches it
  at pointerdown); the card layout's row press is now tested.
- A related video reset in the player forgets the session's stored position.
- Removing the playing video passes over known-dead items and steps the way it went.
- Prev/Next off only because of dead items stay focusable and say why (HU/EN).
- The docked bar's scroller leaves room for focus rings.
- A focus-opened About card is not closed by its own scroll into view.
- EN "Clear watch progress" for the video reset, distinct from a page's "Reset view".
- The signed-out title read goes to the page yt-dlp read; the retitle writes are conditional.
- Tests: the cap of three errors, the bar's own Fullscreen, the group glyph, the backfill's reads.
2026-11-01 05:36:59 +01:00

81 lines
2.6 KiB
TypeScript

// @vitest-environment jsdom
//
// The About cell's card opened the instant a pointer crossed the cell, so scrolling the table over
// a column of them popped card after card. It waits for the pointer to rest on the cell now, and a
// scroll puts an open one away — unless the keyboard's focus opened it, whose own scroll into view
// would put it away the moment it opened.
import { describe, it, expect, vi, afterEach, beforeEach } from "vitest";
import { render, screen, fireEvent, act, cleanup } from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import AboutCell from "./AboutCell";
import { api } from "../../lib/api";
beforeEach(() => {
vi.useFakeTimers();
vi.spyOn(api, "channelDetail").mockReturnValue(new Promise(() => {}));
});
afterEach(() => {
cleanup();
vi.useRealTimers();
vi.restoreAllMocks();
});
function mount() {
const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
render(
<QueryClientProvider client={qc}>
<AboutCell text="An element of truth" channelId="UC1" />
</QueryClientProvider>,
);
return screen.getByText("An element of truth");
}
// Present in the DOM is enough: it paints once floating-ui has placed it, which a fake clock never lets happen.
const card = () => document.querySelector('[role="tooltip"]');
const wait = (ms: number) => act(() => vi.advanceTimersByTime(ms));
const enter = (el: HTMLElement) =>
act(() => {
fireEvent.pointerEnter(el);
fireEvent.mouseEnter(el);
fireEvent.mouseMove(el);
});
describe("AboutCell — the hover card", () => {
it("does not open for a pointer passing over the cell", async () => {
const cell = mount();
enter(cell);
await wait(300);
expect(card()).toBeNull();
fireEvent.mouseLeave(cell);
await wait(600);
expect(card()).toBeNull();
});
it("opens once the pointer rests on it", async () => {
const cell = mount();
enter(cell);
await wait(550);
expect(card()).not.toBeNull();
});
it("goes away when the table scrolls", async () => {
const cell = mount();
enter(cell);
await wait(550);
expect(card()).not.toBeNull();
act(() => void window.dispatchEvent(new Event("scroll")));
await wait(50);
expect(card()).toBeNull();
});
it("stays when the focus that opened it scrolls its cell into view", async () => {
const cell = mount();
act(() => cell.focus());
await wait(10);
expect(card()).not.toBeNull();
act(() => void window.dispatchEvent(new Event("scroll")));
await wait(50);
expect(card()).not.toBeNull();
});
});