test: increase strategic coverage
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
import { act, renderHook } from '@testing-library/react'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import {
|
||||
isWithinFormattingToolbarHoverBridge,
|
||||
shouldSuppressFormattingToolbarHoverUpdate,
|
||||
useBlockNoteFormattingToolbarHoverGuard,
|
||||
} from './blockNoteFormattingToolbarHoverGuard'
|
||||
|
||||
function rect(left: number, top: number, width: number, height: number) {
|
||||
return DOMRect.fromRect({ x: left, y: top, width, height })
|
||||
}
|
||||
|
||||
function setRect(element: HTMLElement, nextRect: DOMRect) {
|
||||
element.getBoundingClientRect = () => nextRect
|
||||
}
|
||||
|
||||
function setupHoverDom() {
|
||||
const container = document.createElement('div')
|
||||
const block = document.createElement('div')
|
||||
block.className = 'bn-block'
|
||||
block.dataset.id = 'image-block'
|
||||
const fileBlock = document.createElement('div')
|
||||
fileBlock.dataset.fileBlock = 'true'
|
||||
const wrapper = document.createElement('div')
|
||||
wrapper.className = 'bn-visual-media-wrapper'
|
||||
fileBlock.appendChild(wrapper)
|
||||
block.appendChild(fileBlock)
|
||||
container.appendChild(block)
|
||||
document.body.appendChild(container)
|
||||
|
||||
const toolbar = document.createElement('div')
|
||||
toolbar.className = 'bn-formatting-toolbar'
|
||||
document.body.appendChild(toolbar)
|
||||
|
||||
setRect(wrapper, rect(300, 130, 140, 90))
|
||||
setRect(toolbar, rect(322, 78, 96, 24))
|
||||
|
||||
return { container, toolbar }
|
||||
}
|
||||
|
||||
function createEditor(options: {
|
||||
selectionType?: string | null
|
||||
selectionId?: string
|
||||
cursorType?: string
|
||||
cursorId?: string
|
||||
setTextCursorPosition?: ReturnType<typeof vi.fn>
|
||||
}) {
|
||||
const {
|
||||
selectionType = 'paragraph',
|
||||
selectionId = 'other-block',
|
||||
cursorType = 'paragraph',
|
||||
cursorId = 'cursor-block',
|
||||
setTextCursorPosition = vi.fn(),
|
||||
} = options
|
||||
|
||||
return {
|
||||
getSelection: () => (
|
||||
selectionType
|
||||
? { blocks: [{ type: selectionType, id: selectionId }] }
|
||||
: null
|
||||
),
|
||||
getTextCursorPosition: () => ({ block: { type: cursorType, id: cursorId } }),
|
||||
setTextCursorPosition,
|
||||
}
|
||||
}
|
||||
|
||||
function dispatchBridgeMousemove(target: EventTarget = document.body) {
|
||||
const event = new MouseEvent('mousemove', {
|
||||
bubbles: true,
|
||||
clientX: 368,
|
||||
clientY: 104,
|
||||
})
|
||||
Object.defineProperty(event, 'target', { configurable: true, value: target })
|
||||
const stopPropagation = vi.fn()
|
||||
event.stopPropagation = stopPropagation
|
||||
act(() => {
|
||||
window.dispatchEvent(event)
|
||||
})
|
||||
return stopPropagation
|
||||
}
|
||||
|
||||
describe('blockNoteFormattingToolbarHoverGuard extra coverage', () => {
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
|
||||
it('treats invisible rects and missing bridge inputs as non-suppressing', () => {
|
||||
expect(
|
||||
isWithinFormattingToolbarHoverBridge(
|
||||
{ x: 12, y: 12 },
|
||||
rect(10, 10, 0, 20),
|
||||
rect(10, 10, 20, 20),
|
||||
),
|
||||
).toBe(false)
|
||||
|
||||
expect(
|
||||
shouldSuppressFormattingToolbarHoverUpdate({
|
||||
eventTarget: document.body,
|
||||
point: { x: 12, y: 12 },
|
||||
container: null,
|
||||
doc: document,
|
||||
selectedFileBlockId: 'image-block',
|
||||
}),
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it('remembers the last selected file block while open and clears it when closed', () => {
|
||||
const addSpy = vi.spyOn(window, 'addEventListener')
|
||||
const removeSpy = vi.spyOn(window, 'removeEventListener')
|
||||
const { container } = setupHoverDom()
|
||||
const setTextCursorPosition = vi.fn()
|
||||
const editor = createEditor({ setTextCursorPosition })
|
||||
|
||||
const { rerender, unmount } = renderHook(
|
||||
({ selectedFileBlockId, isOpen }) => useBlockNoteFormattingToolbarHoverGuard({
|
||||
editor: editor as never,
|
||||
container,
|
||||
selectedFileBlockId,
|
||||
isOpen,
|
||||
}),
|
||||
{
|
||||
initialProps: { selectedFileBlockId: 'image-block', isOpen: true },
|
||||
},
|
||||
)
|
||||
|
||||
expect(addSpy).toHaveBeenCalledWith('mousemove', expect.any(Function), true)
|
||||
|
||||
rerender({ selectedFileBlockId: null, isOpen: true })
|
||||
const stopPropagation = dispatchBridgeMousemove()
|
||||
|
||||
expect(setTextCursorPosition).toHaveBeenCalledWith('image-block')
|
||||
expect(stopPropagation).toHaveBeenCalledTimes(1)
|
||||
|
||||
rerender({ selectedFileBlockId: null, isOpen: false })
|
||||
rerender({ selectedFileBlockId: null, isOpen: true })
|
||||
dispatchBridgeMousemove()
|
||||
|
||||
expect(setTextCursorPosition).toHaveBeenCalledTimes(1)
|
||||
|
||||
unmount()
|
||||
expect(removeSpy).toHaveBeenCalledWith('mousemove', expect.any(Function), true)
|
||||
})
|
||||
|
||||
it('skips listener setup when the environment is invalid and safely ignores already-active or failing restores', () => {
|
||||
const addSpy = vi.spyOn(window, 'addEventListener')
|
||||
const { container } = setupHoverDom()
|
||||
const alreadySelectedEditor = createEditor({
|
||||
selectionType: null,
|
||||
cursorType: 'image',
|
||||
cursorId: 'image-block',
|
||||
setTextCursorPosition: vi.fn(),
|
||||
})
|
||||
|
||||
renderHook(() => useBlockNoteFormattingToolbarHoverGuard({
|
||||
editor: alreadySelectedEditor as never,
|
||||
container: null,
|
||||
selectedFileBlockId: 'image-block',
|
||||
isOpen: true,
|
||||
}))
|
||||
|
||||
expect(addSpy).not.toHaveBeenCalled()
|
||||
|
||||
const { unmount } = renderHook(() => useBlockNoteFormattingToolbarHoverGuard({
|
||||
editor: alreadySelectedEditor as never,
|
||||
container,
|
||||
selectedFileBlockId: 'image-block',
|
||||
isOpen: true,
|
||||
}))
|
||||
|
||||
dispatchBridgeMousemove()
|
||||
expect(alreadySelectedEditor.setTextCursorPosition).not.toHaveBeenCalled()
|
||||
|
||||
unmount()
|
||||
|
||||
const throwingEditor = createEditor({
|
||||
selectionType: null,
|
||||
cursorType: 'paragraph',
|
||||
cursorId: 'other-block',
|
||||
setTextCursorPosition: vi.fn(() => {
|
||||
throw new Error('gone')
|
||||
}),
|
||||
})
|
||||
|
||||
renderHook(() => useBlockNoteFormattingToolbarHoverGuard({
|
||||
editor: throwingEditor as never,
|
||||
container,
|
||||
selectedFileBlockId: 'image-block',
|
||||
isOpen: true,
|
||||
}))
|
||||
|
||||
expect(() => dispatchBridgeMousemove()).not.toThrow()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user