// @vitest-environment jsdom /** * What the LinkChip and LinkPreview pages claim, pinned: what each state says, * where the chip leads, and that a screen that cannot hover gets no preview. */ import { act, cleanup, render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { LinkChip } from './LinkChip' import { ITEM, LOADING, ready, SAID, UNAVAILABLE } from './linked.examples' /** A screen that can hover, or one that cannot (a phone, a tablet). */ function screenThatCanHover(canHover: boolean) { vi.stubGlobal('matchMedia', (query: string) => ({ matches: query === '(hover: hover)' ? canHover : false, media: query, addEventListener: () => {}, removeEventListener: () => {}, })) } beforeEach(() => { vi.useFakeTimers({ shouldAdvanceTime: true }) }) afterEach(() => { cleanup() vi.useRealTimers() vi.unstubAllGlobals() }) /** Rest the pointer on the chip past the preview's delay. */ async function hoverChip(name: RegExp) { const user = userEvent.setup({ advanceTimers: vi.advanceTimersByTime }) await user.hover(screen.getByRole('link', { name })) await act(async () => { vi.advanceTimersByTime(1000) }) } describe('LinkChip', () => { it('leads to what it links, with its key and title', () => { render() const link = screen.getByRole('link', { name: /ABC-2/ }) expect(link.getAttribute('href')).toBe('#item') expect(link.textContent).toContain(ITEM.title) }) it('says a person’s words after their name', () => { render() expect(screen.getByRole('link').textContent).toContain(`Person one: ${SAID.body}`) }) it('while it loads, is busy and leads nowhere yet', () => { const { container } = render() expect(container.querySelector('[aria-busy="true"]')).not.toBeNull() expect(screen.queryByRole('link')).toBeNull() }) it('says “not available” in words, and leads nowhere', () => { render() expect(screen.getByText('Item, not available')).toBeTruthy() expect(screen.queryByRole('link')).toBeNull() }) it('shows its card, read only, when the pointer rests on it', async () => { screenThatCanHover(true) render() await hoverChip(/ABC-2/) expect(screen.getByText(ITEM.summary!)).toBeTruthy() // Read only: the values are words, never pickers, though this reader may change them. expect(screen.queryByRole('combobox')).toBeNull() expect(screen.getByText('Person one')).toBeTruthy() }) it('shows no card on a screen that cannot hover, where a tap opens it', async () => { screenThatCanHover(false) render() await hoverChip(/ABC-2/) expect(screen.queryByText(ITEM.summary!)).toBeNull() expect(screen.getByRole('link', { name: /ABC-2/ }).getAttribute('href')).toBe('#item') }) })