// @vitest-environment jsdom /** * The bar's own search field, pinned: given `onSearch` it draws a button with * the words and the shortcut, a click and Ctrl+K or Cmd+K anywhere call it, * a `search` of the caller's own still takes the centre, and without either * the bar draws nothing there and leaves the keys alone. */ import { afterEach, describe, expect, it, vi } from 'vitest' import { cleanup, render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { AppShell } from './AppShell' import { TopBar } from './TopBar' afterEach(cleanup) const press = (init: KeyboardEventInit) => { const event = new KeyboardEvent('keydown', { bubbles: true, cancelable: true, ...init }) window.dispatchEvent(event) return event } describe('TopBar search', () => { it('draws a search field that opens the search', async () => { const onSearch = vi.fn() render() const field = screen.getByRole('button', { name: /Search Peek\.\.\./ }) expect(field.textContent).toMatch(/Ctrl\+K|Cmd\+K/) await userEvent.click(field) expect(onSearch).toHaveBeenCalledTimes(1) }) it('leaves focus where it was on a click', async () => { const onSearch = vi.fn() render( <> , ) const composer = screen.getByRole('textbox', { name: 'composer' }) composer.focus() await userEvent.click(screen.getByRole('button', { name: /Search…/ })) expect(onSearch).toHaveBeenCalledTimes(1) expect(document.activeElement).toBe(composer) }) it('is reached with Tab and pressed with Enter', async () => { const onSearch = vi.fn() render() await userEvent.tab() expect(document.activeElement).toBe(screen.getByRole('button', { name: /Search…/ })) await userEvent.keyboard('{Enter}') expect(onSearch).toHaveBeenCalledTimes(1) }) it('says "Search…" when given no words', () => { render( {}} />) expect(screen.getByRole('button', { name: /Search…/ })).toBeTruthy() }) it.each([ ['Ctrl+K', { ctrlKey: true, key: 'k' }], ['Cmd+K', { metaKey: true, key: 'k' }], ['Ctrl+Shift+K', { ctrlKey: true, shiftKey: true, key: 'K' }], ])('opens the search on %s anywhere', (_name, init) => { const onSearch = vi.fn() render() const event = press(init) expect(onSearch).toHaveBeenCalledTimes(1) expect(event.defaultPrevented).toBe(true) }) it('calls the latest handler', () => { const first = vi.fn() const second = vi.fn() const { rerender } = render() rerender() press({ ctrlKey: true, key: 'k' }) expect(first).not.toHaveBeenCalled() expect(second).toHaveBeenCalledTimes(1) }) it('leaves K alone without a modifier, and the keys alone without onSearch', () => { const onSearch = vi.fn() const { unmount } = render() press({ key: 'k' }) expect(onSearch).not.toHaveBeenCalled() unmount() render() expect(press({ ctrlKey: true, key: 'k' }).defaultPrevented).toBe(false) expect(screen.queryByRole('button')).toBeNull() }) it('stops listening once it is gone', () => { const onSearch = vi.fn() const { unmount } = render() unmount() press({ ctrlKey: true, key: 'k' }) expect(onSearch).not.toHaveBeenCalled() }) it("draws the caller's own centre instead, and still answers the keys", () => { const onSearch = vi.fn() render(own} />) expect(screen.getByText('own')).toBeTruthy() expect(screen.queryByRole('button')).toBeNull() press({ ctrlKey: true, key: 'k' }) expect(onSearch).toHaveBeenCalledTimes(1) }) it('reaches the bar through AppShell', async () => { const onSearch = vi.fn() render( } onSearch={onSearch} searchPlaceholder="Search Peek...">

page

, ) await userEvent.click(screen.getByRole('button', { name: /Search Peek\.\.\./ })) expect(onSearch).toHaveBeenCalledTimes(1) }) })