// @vitest-environment jsdom /** * What the PreviewCard page claims, pinned. * * Split out of `Popover.test.tsx` on 2026-09-08: the two arrived in one * commit and shared a file, and every other component in this package is * tested beside itself. Placement is Floating UI's and is measured in a * browser — jsdom lays nothing out — so what is here is the behaviour. */ import { afterEach, describe, expect, it } from 'vitest' import { cleanup, render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { PreviewCard } from './PreviewCard' afterEach(cleanup) describe('PreviewCard', () => { it('renders its trigger, and nothing of its content, until it opens', () => { render( The rest of it}> A row , ) expect(screen.getByText('A row')).toBeTruthy() // `content` is not rendered while closed, so a preview that fetches does // not fetch once per row on screen. expect(screen.queryByText('The rest of it')).toBeNull() }) it('opens when the pointer rests on the trigger, and closes when it leaves', async () => { const user = userEvent.setup() render( The rest of it} delay={0} closeDelay={0}> A row , ) await user.hover(screen.getByText('A row')) expect(await screen.findByText('The rest of it')).toBeTruthy() await user.unhover(screen.getByText('A row')) expect(screen.queryByText('The rest of it')).toBeNull() }) /* * Not here: "the pointer can move into the card, and it scrolls" — the one * claim that separates this from a tooltip. * * It cannot be tested in jsdom. No stylesheet is loaded there, so the * `pointer-events: none` Base UI puts on the positioner is never reset by * the popup's own class, and user-event refuses to move the pointer into * something it reads as untouchable. Measured in Chrome instead * (2026-09-08, the `Scrolling` story): the popup computes * `pointer-events: auto`, the card stays open when the pointer moves into * it, its 537px of content scrolls inside a 298px box — scrollTop 0 → 200 * on a wheel — and it closes when the pointer leaves for good. */ /** The page says so in its Keys table, and a card the pointer can enter is * a layer, so it owes the exit every layer owes. */ it('closes on Escape', async () => { const user = userEvent.setup() render( The rest of it} delay={0} closeDelay={0}> A row , ) await user.hover(screen.getByText('A row')) await screen.findByText('The rest of it') await user.keyboard('{Escape}') expect(screen.queryByText('The rest of it')).toBeNull() }) it('the trigger is the wrapper, and the row inside it is untouched', () => { const { container } = render( x} wrapperClassName="block w-full">
A row
, ) const wrapper = container.firstElementChild as HTMLElement expect(wrapper.tagName).toBe('SPAN') expect(wrapper.className).toContain('block') expect(wrapper.firstElementChild?.getAttribute('data-testid')).toBe('row') }) })