diff --git a/src/__tests__/helpers/utils.js b/src/__tests__/helpers/utils.js
index f72ba8d3..dc051a4a 100644
--- a/src/__tests__/helpers/utils.js
+++ b/src/__tests__/helpers/utils.js
@@ -1,4 +1,5 @@
import {eventMap} from '@testing-library/dom/dist/event-map'
+import {isElementType} from '../../utils'
// this is pretty helpful:
// https://codesandbox.io/s/quizzical-worker-eo909
@@ -126,7 +127,7 @@ function addEventListener(el, type, listener, options) {
}
function getElementValue(element) {
- if (element.tagName === 'SELECT' && element.multiple) {
+ if (isElementType(element, 'select') && element.multiple) {
return JSON.stringify(Array.from(element.selectedOptions).map(o => o.value))
} else if (element.getAttribute('role') === 'listbox') {
return JSON.stringify(
@@ -137,7 +138,7 @@ function getElementValue(element) {
} else if (
element.type === 'checkbox' ||
element.type === 'radio' ||
- element.tagName === 'BUTTON'
+ isElementType(element, 'button')
) {
// handled separately
return null
@@ -156,7 +157,7 @@ function getElementDisplayName(element) {
element.htmlFor ? `[for="${element.htmlFor}"]` : null,
value ? `[value=${value}]` : null,
hasChecked ? `[checked=${element.checked}]` : null,
- element.tagName === 'OPTION' ? `[selected=${element.selected}]` : null,
+ isElementType(element, 'option') ? `[selected=${element.selected}]` : null,
element.getAttribute('role') === 'option'
? `[aria-selected=${element.getAttribute('aria-selected')}]`
: null,
@@ -197,7 +198,7 @@ function addListeners(element, {eventHandlers = {}} = {}) {
})
}
// prevent default of submits in tests
- if (element.tagName === 'FORM') {
+ if (isElementType(element, 'form')) {
addEventListener(element, 'submit', e => e.preventDefault())
}
diff --git a/src/__tests__/utils.js b/src/__tests__/utils.js
index 680f5cfa..b97c814c 100644
--- a/src/__tests__/utils.js
+++ b/src/__tests__/utils.js
@@ -1,75 +1,44 @@
-import { screen } from '@testing-library/dom'
-import {isInstanceOfElement, isVisible} from '../utils'
+import {screen} from '@testing-library/dom'
+import {isElementType, isVisible} from '../utils'
import {setup} from './helpers/utils'
-// isInstanceOfElement can be removed once the peerDependency for @testing-library/dom is bumped to a version that includes https://github.com/testing-library/dom-testing-library/pull/885
-describe('check element type per isInstanceOfElement', () => {
- let defaultViewDescriptor, spanDescriptor
- beforeAll(() => {
- defaultViewDescriptor = Object.getOwnPropertyDescriptor(
- Object.getPrototypeOf(global.document),
- 'defaultView',
- )
- spanDescriptor = Object.getOwnPropertyDescriptor(
- global.window,
- 'HTMLSpanElement',
- )
- })
- afterEach(() => {
- Object.defineProperty(
- Object.getPrototypeOf(global.document),
- 'defaultView',
- defaultViewDescriptor,
- )
- Object.defineProperty(global.window, 'HTMLSpanElement', spanDescriptor)
+describe('check element type per namespace, tagname and props', () => {
+ test('check in HTML document', () => {
+ const {elements} = setup(``)
+
+ expect(isElementType(elements[0], 'input')).toBe(true)
+ expect(isElementType(elements[0], 'input', {readOnly: false})).toBe(false)
+ expect(isElementType(elements[1], 'input')).toBe(false)
+ expect(isElementType(elements[1], ['input', 'textarea'])).toBe(true)
+ expect(
+ isElementType(elements[1], ['input', 'textarea'], {readOnly: false}),
+ ).toBe(true)
})
- test('check in regular jest environment', () => {
- const {element} = setup(``)
-
- expect(element.ownerDocument.defaultView).toEqual(
- expect.objectContaining({
- HTMLSpanElement: expect.any(Function),
- }),
+ test('check in XML document', () => {
+ // const {element} = setup(``)
+ const dom = new DOMParser().parseFromString(
+ `
+
+
+
+
+ `,
+ 'application/xml',
)
-
- expect(isInstanceOfElement(element, 'HTMLSpanElement')).toBe(true)
- expect(isInstanceOfElement(element, 'HTMLDivElement')).toBe(false)
- })
-
- test('check in detached document', () => {
- const {element} = setup(``)
-
- Object.defineProperty(
- Object.getPrototypeOf(element.ownerDocument),
- 'defaultView',
- {value: null},
- )
-
- expect(element.ownerDocument.defaultView).toBe(null)
-
- expect(isInstanceOfElement(element, 'HTMLSpanElement')).toBe(true)
- expect(isInstanceOfElement(element, 'HTMLDivElement')).toBe(false)
- })
-
- test('check in environment not providing constructors on window', () => {
- const {element} = setup(``)
-
- delete global.window.HTMLSpanElement
-
- expect(element.ownerDocument.defaultView.HTMLSpanElement).toBe(undefined)
-
- expect(isInstanceOfElement(element, 'HTMLSpanElement')).toBe(true)
- expect(isInstanceOfElement(element, 'HTMLDivElement')).toBe(false)
- })
-
- test('throw error if element is not created by HTML*Element constructor', () => {
- const doc = new Document()
-
- // constructor is global.Element
- const element = doc.createElement('span')
-
- expect(() => isInstanceOfElement(element, 'HTMLSpanElement')).toThrow()
+ const xmlInput = dom.getElementsByTagNameNS(
+ 'http://example.com/foo',
+ 'input',
+ )[0]
+ const htmlInput = dom.getElementsByTagNameNS(
+ 'http://www.w3.org/1999/xhtml',
+ 'input',
+ )[0]
+
+ expect(isElementType(xmlInput, 'input')).toBe(false)
+ expect(isElementType(htmlInput, 'input')).toBe(true)
+ expect(isElementType(htmlInput, 'input', {readOnly: true})).toBe(true)
+ expect(isElementType(htmlInput, 'input', {readOnly: false})).toBe(false)
})
})
diff --git a/src/clear.ts b/src/clear.ts
index a8946e3f..30f6c529 100644
--- a/src/clear.ts
+++ b/src/clear.ts
@@ -1,26 +1,22 @@
-import {isDisabled, isInstanceOfElement} from './utils'
+import {isDisabled, isElementType} from './utils'
import {type} from './type'
function clear(element: Element) {
- if (
- !isInstanceOfElement(element, 'HTMLInputElement') &&
- !isInstanceOfElement(element, 'HTMLTextAreaElement')
- ) {
+ if (!isElementType(element, ['input', 'textarea'])) {
// TODO: support contenteditable
throw new Error(
'clear currently only supports input and textarea elements.',
)
}
- const el = element as HTMLInputElement | HTMLTextAreaElement
- if (isDisabled(el)) {
+ if (isDisabled(element)) {
return
}
// TODO: track the selection range ourselves so we don't have to do this input "type" trickery
// just like cypress does: https://github.com/cypress-io/cypress/blob/8d7f1a0bedc3c45a2ebf1ff50324b34129fdc683/packages/driver/src/dom/selection.ts#L16-L37
- const elementType = el.type
+ const elementType = element.type
if (elementType !== 'textarea') {
// setSelectionRange is not supported on certain types of inputs, e.g. "number" or "email"
@@ -30,13 +26,13 @@ function clear(element: Element) {
type(element, '{selectall}{del}', {
delay: 0,
initialSelectionStart:
- el.selectionStart ?? /* istanbul ignore next */ undefined,
+ element.selectionStart ?? /* istanbul ignore next */ undefined,
initialSelectionEnd:
- el.selectionEnd ?? /* istanbul ignore next */ undefined,
+ element.selectionEnd ?? /* istanbul ignore next */ undefined,
})
if (elementType !== 'textarea') {
- ;(el as HTMLInputElement).type = elementType
+ ;(element as HTMLInputElement).type = elementType
}
}
diff --git a/src/click.ts b/src/click.ts
index 0f1cfcb1..04af1cd7 100644
--- a/src/click.ts
+++ b/src/click.ts
@@ -4,7 +4,7 @@ import {
isLabelWithInternallyDisabledControl,
isFocusable,
isDisabled,
- isInstanceOfElement,
+ isElementType,
} from './utils'
import {hover} from './hover'
import {blur} from './blur'
@@ -119,14 +119,13 @@ function click(
) {
if (!skipHover) hover(element, init)
- if (isInstanceOfElement(element, 'HTMLLabelElement')) {
- clickLabel(element as HTMLLabelElement, init, {clickCount})
- } else if (isInstanceOfElement(element, 'HTMLInputElement')) {
- const el = element as HTMLInputElement
- if (el.type === 'checkbox' || el.type === 'radio') {
- clickBooleanElement(el, init, {clickCount})
+ if (isElementType(element, 'label')) {
+ clickLabel(element, init, {clickCount})
+ } else if (isElementType(element, 'input')) {
+ if (element.type === 'checkbox' || element.type === 'radio') {
+ clickBooleanElement(element, init, {clickCount})
} else {
- clickElement(el, init, {clickCount})
+ clickElement(element, init, {clickCount})
}
} else {
clickElement(element, init, {clickCount})
diff --git a/src/keyboard/plugins/arrow.ts b/src/keyboard/plugins/arrow.ts
index 4455d7f1..92b4d7da 100644
--- a/src/keyboard/plugins/arrow.ts
+++ b/src/keyboard/plugins/arrow.ts
@@ -4,14 +4,14 @@
*/
import {behaviorPlugin} from '../types'
-import {isInstanceOfElement, setSelectionRangeIfNecessary} from '../../utils'
+import {isElementType, setSelectionRangeIfNecessary} from '../../utils'
export const keydownBehavior: behaviorPlugin[] = [
{
// TODO: implement for textarea and contentEditable
matches: (keyDef, element) =>
(keyDef.key === 'ArrowLeft' || keyDef.key === 'ArrowRight') &&
- isInstanceOfElement(element, 'HTMLInputElement'),
+ isElementType(element, 'input'),
handle: (keyDef, element) => {
const {selectionStart, selectionEnd} = element as HTMLInputElement
diff --git a/src/keyboard/plugins/character.ts b/src/keyboard/plugins/character.ts
index f8ca9856..00c02790 100644
--- a/src/keyboard/plugins/character.ts
+++ b/src/keyboard/plugins/character.ts
@@ -10,7 +10,7 @@ import {
calculateNewValue,
getValue,
isContentEditable,
- isInstanceOfElement,
+ isElementType,
isValidDateValue,
isValidInputTimeValue,
} from '../../utils'
@@ -19,8 +19,7 @@ export const keypressBehavior: behaviorPlugin[] = [
{
matches: (keyDef, element) =>
keyDef.key?.length === 1 &&
- isInstanceOfElement(element, 'HTMLInputElement') &&
- (element as HTMLInputElement).type === 'time',
+ isElementType(element, 'input', {type: 'time'}),
handle: (keyDef, element, options, state) => {
let newEntry = keyDef.key as string
@@ -62,8 +61,7 @@ export const keypressBehavior: behaviorPlugin[] = [
{
matches: (keyDef, element) =>
keyDef.key?.length === 1 &&
- isInstanceOfElement(element, 'HTMLInputElement') &&
- (element as HTMLInputElement).type === 'date',
+ isElementType(element, 'input', {type: 'date'}),
handle: (keyDef, element, options, state) => {
let newEntry = keyDef.key as string
@@ -103,8 +101,7 @@ export const keypressBehavior: behaviorPlugin[] = [
{
matches: (keyDef, element) =>
keyDef.key?.length === 1 &&
- isInstanceOfElement(element, 'HTMLInputElement') &&
- (element as HTMLInputElement).type === 'number',
+ isElementType(element, 'input', {type: 'number'}),
handle: (keyDef, element, options, state) => {
if (!/[\d.\-e]/.test(keyDef.key as string)) {
return
@@ -140,8 +137,7 @@ export const keypressBehavior: behaviorPlugin[] = [
{
matches: (keyDef, element) =>
keyDef.key?.length === 1 &&
- (isInstanceOfElement(element, 'HTMLInputElement') ||
- isInstanceOfElement(element, 'HTMLTextAreaElement') ||
+ (isElementType(element, ['input', 'textarea']) ||
isContentEditable(element)),
handle: (keyDef, element) => {
const {newValue, newSelectionStart} = calculateNewValue(
@@ -163,8 +159,7 @@ export const keypressBehavior: behaviorPlugin[] = [
{
matches: (keyDef, element) =>
keyDef.key === 'Enter' &&
- (isInstanceOfElement(element, 'HTMLTextAreaElement') ||
- isContentEditable(element)),
+ (isElementType(element, 'textarea') || isContentEditable(element)),
handle: (keyDef, element, options, state) => {
const {newValue, newSelectionStart} = calculateNewValue(
'\n',
diff --git a/src/keyboard/plugins/control.ts b/src/keyboard/plugins/control.ts
index 304129b7..a5fa8b46 100644
--- a/src/keyboard/plugins/control.ts
+++ b/src/keyboard/plugins/control.ts
@@ -7,7 +7,7 @@ import {behaviorPlugin} from '../types'
import {
getValue,
isContentEditable,
- isInstanceOfElement,
+ isElementType,
setSelectionRangeIfNecessary,
} from '../../utils'
import {fireInputEventIfNeeded} from '../shared'
@@ -17,8 +17,7 @@ export const keydownBehavior: behaviorPlugin[] = [
{
matches: (keyDef, element) =>
(keyDef.key === 'Home' || keyDef.key === 'End') &&
- (isInstanceOfElement(element, 'HTMLInputElement') ||
- isInstanceOfElement(element, 'HTMLTextAreaElement') ||
+ (isElementType(element, ['input', 'textarea']) ||
isContentEditable(element)),
handle: (keyDef, element) => {
// This could probably been improved by collapsing a selection range
diff --git a/src/keyboard/plugins/functional.ts b/src/keyboard/plugins/functional.ts
index 66c4c7ac..5d209a3c 100644
--- a/src/keyboard/plugins/functional.ts
+++ b/src/keyboard/plugins/functional.ts
@@ -4,7 +4,7 @@
*/
import {fireEvent} from '@testing-library/dom'
-import {getValue, isClickableInput, isInstanceOfElement} from '../../utils'
+import {getValue, isClickableInput, isElementType} from '../../utils'
import {getKeyEventProps, getMouseEventProps} from '../getEventProps'
import {fireInputEventIfNeeded} from '../shared'
import {behaviorPlugin} from '../types'
@@ -78,16 +78,14 @@ export const keypressBehavior: behaviorPlugin[] = [
keyDef.key === 'Enter' &&
(isClickableInput(element) ||
// Links with href defined should handle Enter the same as a click
- (isInstanceOfElement(element, 'HTMLAnchorElement') &&
- Boolean((element as HTMLAnchorElement).href))),
+ (isElementType(element, 'a') && Boolean(element.href))),
handle: (keyDef, element, options, state) => {
fireEvent.click(element, getMouseEventProps(state))
},
},
{
matches: (keyDef, element) =>
- keyDef.key === 'Enter' &&
- isInstanceOfElement(element, 'HTMLInputElement'),
+ keyDef.key === 'Enter' && isElementType(element, 'input'),
handle: (keyDef, element) => {
const form = (element as HTMLInputElement).form
diff --git a/src/keyboard/plugins/index.ts b/src/keyboard/plugins/index.ts
index 1cfd9380..d7130e01 100644
--- a/src/keyboard/plugins/index.ts
+++ b/src/keyboard/plugins/index.ts
@@ -1,5 +1,5 @@
import {behaviorPlugin} from '../types'
-import {isInstanceOfElement} from '../../utils'
+import {isElementType} from '../../utils'
import * as arrowKeys from './arrow'
import * as controlKeys from './control'
import * as characterKeys from './character'
@@ -9,8 +9,7 @@ export const replaceBehavior: behaviorPlugin[] = [
{
matches: (keyDef, element) =>
keyDef.key === 'selectall' &&
- (isInstanceOfElement(element, 'HTMLInputElement') ||
- isInstanceOfElement(element, 'HTMLTextAreaElement')),
+ isElementType(element, ['input', 'textarea']),
handle: (keyDef, element) => {
;(element as HTMLInputElement).select()
},
diff --git a/src/keyboard/shared/fireInputEventIfNeeded.ts b/src/keyboard/shared/fireInputEventIfNeeded.ts
index 2c468dc4..de3cffbe 100644
--- a/src/keyboard/shared/fireInputEventIfNeeded.ts
+++ b/src/keyboard/shared/fireInputEventIfNeeded.ts
@@ -1,6 +1,6 @@
import {fireEvent} from '@testing-library/dom'
import {
- isInstanceOfElement,
+ isElementType,
isClickableInput,
getValue,
isContentEditable,
@@ -53,11 +53,5 @@ export function fireInputEventIfNeeded({
}
function isReadonly(element: Element): boolean {
- if (
- !isInstanceOfElement(element, 'HTMLInputElement') &&
- !isInstanceOfElement(element, 'HTMLTextAreaElement')
- ) {
- return false
- }
- return (element as HTMLInputElement | HTMLTextAreaElement).readOnly
+ return isElementType(element, ['input', 'textarea'], {readOnly: true})
}
diff --git a/src/select-options.ts b/src/select-options.ts
index 0bbd0eda..c9922242 100644
--- a/src/select-options.ts
+++ b/src/select-options.ts
@@ -1,5 +1,5 @@
import {createEvent, getConfig, fireEvent} from '@testing-library/dom'
-import {isDisabled, isInstanceOfElement} from './utils'
+import {isDisabled, isElementType} from './utils'
import {click} from './click'
import {focus} from './focus'
import {hover, unhover} from './hover'
@@ -44,8 +44,8 @@ function selectOptionsBase(
if (isDisabled(select) || !selectedOptions.length) return
- if (isInstanceOfElement(select, 'HTMLSelectElement')) {
- if ((select as HTMLSelectElement).multiple) {
+ if (isElementType(select, 'select')) {
+ if (select.multiple) {
for (const option of selectedOptions) {
// events fired for multiple select are weird. Can't use hover...
fireEvent.pointerOver(option, init)
diff --git a/src/upload.ts b/src/upload.ts
index 0cae629e..8615b379 100644
--- a/src/upload.ts
+++ b/src/upload.ts
@@ -2,7 +2,7 @@ import {fireEvent, createEvent} from '@testing-library/dom'
import {click} from './click'
import {blur} from './blur'
import {focus} from './focus'
-import {isDisabled, isInstanceOfElement} from './utils'
+import {isDisabled, isElementType} from './utils'
interface uploadInit {
clickInit?: MouseEventInit
@@ -23,9 +23,9 @@ function upload(
click(element, init?.clickInit)
- const input = isInstanceOfElement(element, 'HTMLLabelElement')
- ? ((element as HTMLLabelElement).control as HTMLInputElement)
- : (element as HTMLInputElement)
+ const input = isElementType(element, 'label')
+ ? (element.control as HTMLInputElement)
+ : element
const files = (Array.isArray(fileOrFiles) ? fileOrFiles : [fileOrFiles])
.filter(file => !applyAccept || isAcceptableFile(file, input.accept))
diff --git a/src/utils/click/isClickableInput.ts b/src/utils/click/isClickableInput.ts
index 88f47687..26054dee 100644
--- a/src/utils/click/isClickableInput.ts
+++ b/src/utils/click/isClickableInput.ts
@@ -1,4 +1,4 @@
-import {isInstanceOfElement} from '../misc/isInstanceOfElement'
+import {isElementType} from '../misc/isElementType'
const CLICKABLE_INPUT_TYPES = [
'button',
@@ -11,8 +11,8 @@ const CLICKABLE_INPUT_TYPES = [
export function isClickableInput(element: Element): boolean {
return (
- element.tagName === 'BUTTON' ||
- (isInstanceOfElement(element, 'HTMLInputElement') &&
- CLICKABLE_INPUT_TYPES.includes((element as HTMLInputElement).type))
+ isElementType(element, 'button') ||
+ (isElementType(element, 'input') &&
+ CLICKABLE_INPUT_TYPES.includes(element.type))
)
}
diff --git a/src/utils/edit/calculateNewValue.ts b/src/utils/edit/calculateNewValue.ts
index 5ec09bf2..3a564fe7 100644
--- a/src/utils/edit/calculateNewValue.ts
+++ b/src/utils/edit/calculateNewValue.ts
@@ -1,3 +1,4 @@
+import {isElementType} from 'utils/misc/isElementType'
import {getSelectionRange} from './getSelectionRange'
import {getValue} from './getValue'
import {isValidDateValue} from './isValidDateValue'
@@ -97,9 +98,9 @@ function getSanitizedMaxLength(element: Element) {
}
function supportsMaxLength(element: Element) {
- if (element.tagName === 'TEXTAREA') return true
+ if (isElementType(element, 'textarea')) return true
- if (element.tagName === 'INPUT') {
+ if (isElementType(element, 'input')) {
const type = element.getAttribute('type')
// Missing value default is "text"
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 6d5a2294..b653b6ba 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -15,7 +15,7 @@ export * from './focus/isFocusable'
export * from './focus/selector'
export * from './misc/eventWrapper'
-export * from './misc/isInstanceOfElement'
+export * from './misc/isElementType'
export * from './misc/isLabelWithInternallyDisabledControl'
export * from './misc/isVisible'
export * from './misc/isDisabled'
diff --git a/src/utils/misc/isElementType.ts b/src/utils/misc/isElementType.ts
new file mode 100644
index 00000000..91f423f9
--- /dev/null
+++ b/src/utils/misc/isElementType.ts
@@ -0,0 +1,34 @@
+type tag = keyof HTMLElementTagNameMap
+
+export function isElementType<
+ T extends tag,
+ P extends {[k: string]: unknown} | undefined = undefined
+>(
+ element: Element,
+ tag: T | T[],
+ props?: P,
+): element is P extends undefined
+ ? HTMLElementTagNameMap[T]
+ : HTMLElementTagNameMap[T] & P {
+ if (
+ element.namespaceURI &&
+ element.namespaceURI !== 'http://www.w3.org/1999/xhtml'
+ ) {
+ return false
+ }
+
+ tag = Array.isArray(tag) ? tag : [tag]
+
+ // tagName is uppercase in HTMLDocument and lowercase in XMLDocument
+ if (!tag.includes(element.tagName.toLowerCase() as T)) {
+ return false
+ }
+
+ if (props) {
+ return Object.entries(props as NonNullable
).every(
+ ([k, v]) => element[k as keyof Element] === v,
+ )
+ }
+
+ return true
+}
diff --git a/src/utils/misc/isInstanceOfElement.ts b/src/utils/misc/isInstanceOfElement.ts
deleted file mode 100644
index a2302c24..00000000
--- a/src/utils/misc/isInstanceOfElement.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import {getWindowFromNode} from '@testing-library/dom/dist/helpers'
-
-// isInstanceOfElement can be removed once the peerDependency for @testing-library/dom is bumped to a version that includes https://github.com/testing-library/dom-testing-library/pull/885
-/**
- * Check if an element is of a given type.
- *
- * @param {Element} element The element to test
- * @param {string} elementType Constructor name. E.g. 'HTMLSelectElement'
- */
-export function isInstanceOfElement(
- element: Element,
- elementType: string,
- // TODO: make this a type guard
- // This should be typed as a type guard, but there is no map with constructor names to element constructors.
- // Window does not have the constructors as properties.
-): boolean {
- try {
- // Window usually has the element constructors as properties but is not required to do so per specs
- const constructor = getWindowFromNode(element)[
- elementType as keyof Window
- ] as unknown
- if (typeof constructor === 'function') {
- return element instanceof constructor
- }
- } catch {
- // The document might not be associated with a window
- }
-
- // Fall back to the constructor name as workaround for test environments that
- // a) not associate the document with a window
- // b) not provide the constructor as property of window
- if (/^HTML(\w+)Element$/.test(element.constructor.name)) {
- return element.constructor.name === elementType
- }
-
- // The user passed some node that is not created in a browser-like environment
- throw new Error(
- `Unable to verify if element is instance of ${elementType}. Please file an issue describing your test environment: https://github.com/testing-library/dom-testing-library/issues/new`,
- )
-}
diff --git a/src/utils/misc/isLabelWithInternallyDisabledControl.ts b/src/utils/misc/isLabelWithInternallyDisabledControl.ts
index 86020a19..b34d4f0b 100644
--- a/src/utils/misc/isLabelWithInternallyDisabledControl.ts
+++ b/src/utils/misc/isLabelWithInternallyDisabledControl.ts
@@ -2,15 +2,15 @@
// if that control is disabled. NUTS!
import {isDisabled} from './isDisabled'
-import {isInstanceOfElement} from './isInstanceOfElement'
+import {isElementType} from './isElementType'
// no joke. There are NO events for: