Files
aiturk-hermes-ide/apps/desktop/src/lib/middle-click.test.tsx
T

87 lines
2.7 KiB
TypeScript

import { cleanup, fireEvent, render, screen } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { middleClickHandlers } from './middle-click'
afterEach(cleanup)
/** A middle click as a real three-button mouse delivers it. Chromium on
* Windows/Linux swallows the trailing `auxclick` when the press starts
* autoscroll, so the gesture may NOT depend on that event. */
function middleClick(element: Element, upOn: Element = element) {
fireEvent.mouseDown(element, { button: 1 })
fireEvent.pointerDown(element, { button: 1 })
fireEvent.pointerUp(upOn, { button: 1 })
}
function Target({ action, id = 'target' }: { action?: () => void; id?: string }) {
return (
<button {...middleClickHandlers(action)} id={id} type="button">
{id}
</button>
)
}
describe('middleClickHandlers', () => {
it('fires without an auxclick — the event Chromium eats when autoscroll starts', () => {
const action = vi.fn()
render(<Target action={action} />)
middleClick(screen.getByText('target'))
expect(action).toHaveBeenCalledTimes(1)
})
it('cancels mousedown so the autoscroll pan widget never appears', () => {
render(<Target action={vi.fn()} />)
const down = fireEvent.mouseDown(screen.getByText('target'), { button: 1 })
expect(down).toBe(false) // preventDefault() called
})
it('cancels the middle mousedown even with no action — the surface owns the button', () => {
render(<Target />)
expect(fireEvent.mouseDown(screen.getByText('target'), { button: 1 })).toBe(false)
})
it('ignores left and right buttons', () => {
const action = vi.fn()
render(<Target action={action} />)
const target = screen.getByText('target')
fireEvent.pointerDown(target, { button: 0 })
fireEvent.pointerUp(target, { button: 0 })
fireEvent.pointerDown(target, { button: 2 })
fireEvent.pointerUp(target, { button: 2 })
expect(action).not.toHaveBeenCalled()
})
it('does nothing when the release lands on a different element', () => {
const pressed = vi.fn()
const released = vi.fn()
render(
<>
<Target action={pressed} id="pressed" />
<Target action={released} id="released" />
</>
)
middleClick(screen.getByText('pressed'), screen.getByText('released'))
expect(pressed).not.toHaveBeenCalled()
expect(released).not.toHaveBeenCalled()
})
it('a press with no action cannot arm the NEXT element it releases over', () => {
const action = vi.fn()
render(
<>
<Target id="inert" />
<Target action={action} id="live" />
</>
)
middleClick(screen.getByText('inert'), screen.getByText('live'))
expect(action).not.toHaveBeenCalled()
})
})