UNPKG

@testing-library/user-event

Version:
102 lines (99 loc) 3.12 kB
import { dispatchDOMEvent } from '../event/dispatchEvent.js'; import '../utils/dataTransfer/Clipboard.js'; import { getActiveElement } from '../utils/focus/getActiveElement.js'; import '@testing-library/dom'; const patched = Symbol('patched focus/blur methods'); function patchFocus(HTMLElement) { if (HTMLElement.prototype[patched]) { return; } // eslint-disable-next-line @typescript-eslint/unbound-method const { focus, blur } = HTMLElement.prototype; Object.defineProperties(HTMLElement.prototype, { focus: { configurable: true, get: ()=>patchedFocus }, blur: { configurable: true, get: ()=>patchedBlur }, [patched]: { configurable: true, get: ()=>({ focus, blur }) } }); let activeCall; function patchedFocus(options) { if (this.ownerDocument.visibilityState !== 'hidden') { return focus.call(this, options); } const blurred = getActiveTarget(this.ownerDocument); if (blurred === this) { return; } const thisCall = Symbol('focus call'); activeCall = thisCall; if (blurred) { blur.call(blurred); dispatchDOMEvent(blurred, 'blur', { relatedTarget: this }); dispatchDOMEvent(blurred, 'focusout', { relatedTarget: activeCall === thisCall ? this : null }); } if (activeCall === thisCall) { focus.call(this, options); dispatchDOMEvent(this, 'focus', { relatedTarget: blurred }); } if (activeCall === thisCall) { dispatchDOMEvent(this, 'focusin', { relatedTarget: blurred }); } } function patchedBlur() { if (this.ownerDocument.visibilityState !== 'hidden') { return blur.call(this); } const blurred = getActiveTarget(this.ownerDocument); if (blurred !== this) { return; } const thisCall = Symbol('blur call'); activeCall = thisCall; blur.call(this); dispatchDOMEvent(blurred, 'blur', { relatedTarget: null }); dispatchDOMEvent(blurred, 'focusout', { relatedTarget: null }); } } function getActiveTarget(document) { const active = getActiveElement(document); return (active === null || active === undefined ? undefined : active.tagName) === 'BODY' ? null : active; } function restoreFocus(HTMLElement) { if (HTMLElement.prototype[patched]) { const { focus, blur } = HTMLElement.prototype[patched]; Object.defineProperties(HTMLElement.prototype, { focus: { configurable: true, get: ()=>focus }, blur: { configurable: true, get: ()=>blur } }); } } export { patchFocus, restoreFocus };