// @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( , ); 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(); }); });