diff --git a/src/__tests__/helpers/dom-event-map.d.ts b/src/__tests__/helpers/dom-event-map.d.ts new file mode 100644 index 00000000..ed4007a3 --- /dev/null +++ b/src/__tests__/helpers/dom-event-map.d.ts @@ -0,0 +1,9 @@ +declare module '@testing-library/dom/dist/event-map' { + export const eventMap: Record< + string, + { + EventType: string + defaultInit: EventInit + } + > +} diff --git a/src/__tests__/helpers/utils.js b/src/__tests__/helpers/utils.ts similarity index 59% rename from src/__tests__/helpers/utils.js rename to src/__tests__/helpers/utils.ts index 36a4e474..5f0c36fb 100644 --- a/src/__tests__/helpers/utils.js +++ b/src/__tests__/helpers/utils.ts @@ -7,25 +7,48 @@ import {isElementType} from '../../utils' // all of the stuff below is complex magic that makes the simpler tests work // sorrynotsorry... -const unstringSnapshotSerializer = { - test: val => val && val.hasOwnProperty('snapshot'), - print: val => val.snapshot, +const unstringSnapshotSerializer: jest.SnapshotSerializerPlugin = { + test: (val: unknown) => + Boolean( + typeof val === 'object' + ? Object.prototype.hasOwnProperty.call(val, 'snapshot') + : false, + ), + print: val => String((<null | {snapshot?: string}>val)?.snapshot), } expect.addSnapshotSerializer(unstringSnapshotSerializer) -function setup(ui, {eventHandlers} = {}) { +type EventHandlers = Record<string, EventListener> + +// The HTMLCollection in lib.d.ts does not allow array access +type HTMLCollection<Elements extends Array<Element>> = Elements & { + item<N extends number>(i: N): Elements[N] +} + +function setup<Elements extends Element | Element[] = HTMLElement>( + ui: string, + { + eventHandlers, + }: { + eventHandlers?: EventHandlers + } = {}, +) { const div = document.createElement('div') div.innerHTML = ui.trim() document.body.append(div) + type ElementsArray = Elements extends Array<Element> ? Elements : [Elements] return { - element: div.firstChild, - elements: div.children, + element: div.firstChild as ElementsArray[0], + elements: div.children as unknown as HTMLCollection<ElementsArray>, // for single elements add the listeners to the element for capturing non-bubbling events - ...addListeners(div.children.length === 1 ? div.firstChild : div, { - eventHandlers, - }), + ...addListeners( + div.children.length === 1 ? (div.firstChild as Element) : div, + { + eventHandlers, + }, + ), } } @@ -49,7 +72,7 @@ function setupSelect({ </select> ` document.body.append(form) - const select = form.querySelector('select') + const select = form.querySelector('select') as HTMLSelectElement const options = Array.from(form.querySelectorAll('option')) return { ...addListeners(select), @@ -76,17 +99,22 @@ function setupListbox() { </ul> ` document.body.append(wrapper) - const listbox = wrapper.querySelector('[role="listbox"]') - const options = Array.from(wrapper.querySelectorAll('[role="option"]')) + const listbox = wrapper.querySelector('[role="listbox"]') as HTMLUListElement + const options = Array.from( + wrapper.querySelectorAll<HTMLElement>('[role="option"]'), + ) // the user is responsible for handling aria-selected on listbox options options.forEach(el => - el.addEventListener('click', e => - e.target.setAttribute( + el.addEventListener('click', e => { + const target = e.currentTarget as HTMLElement + target.setAttribute( 'aria-selected', - JSON.stringify(!JSON.parse(e.target.getAttribute('aria-selected'))), - ), - ), + JSON.stringify( + !JSON.parse(String(target.getAttribute('aria-selected'))), + ), + ) + }), ) return { @@ -97,7 +125,7 @@ function setupListbox() { } const eventLabelGetters = { - KeyboardEvent(event) { + KeyboardEvent(event: KeyboardEvent) { return [ event.key, typeof event.keyCode === 'undefined' ? null : `(${event.keyCode})`, @@ -105,9 +133,9 @@ const eventLabelGetters = { .join(' ') .trim() }, - MouseEvent(event) { + MouseEvent(event: MouseEvent) { // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button - const mouseButtonMap = { + const mouseButtonMap: Record<number, string> = { 0: 'Left', 1: 'Middle', 2: 'Right', @@ -116,20 +144,29 @@ const eventLabelGetters = { } return `${mouseButtonMap[event.button]} (${event.button})` }, -} +} as const -let eventListeners = [] +let eventListeners: Array<{ + el: EventTarget + type: string + listener: EventListener +}> = [] // asside from the hijacked listener stuff here, it's also important to call // this function rather than simply calling addEventListener yourself // because it adds your listener to an eventListeners array which is cleaned // up automatically which will help use avoid memory leaks. -function addEventListener(el, type, listener, options) { +function addEventListener( + el: EventTarget, + type: string, + listener: EventListener, + options?: AddEventListenerOptions, +) { eventListeners.push({el, type, listener}) el.addEventListener(type, listener, options) } -function getElementValue(element) { +function getElementValue(element: Element) { if (isElementType(element, 'select') && element.multiple) { return JSON.stringify(Array.from(element.selectedOptions).map(o => o.value)) } else if (element.getAttribute('role') === 'listbox') { @@ -139,25 +176,38 @@ function getElementValue(element) { } else if (element.getAttribute('role') === 'option') { return JSON.stringify(element.innerHTML) } else if ( - element.type === 'checkbox' || - element.type === 'radio' || + isElementType(element, 'input', {type: 'checkbox'}) || + isElementType(element, 'input', {type: 'radio'}) || isElementType(element, 'button') ) { // handled separately return null } - return JSON.stringify(element.value) + return JSON.stringify((element as HTMLInputElement).value) } -function getElementDisplayName(element) { +function hasProperty<T extends {}, K extends PropertyKey>( + obj: T, + prop: K, +): obj is T & {[k in K]: unknown} { + return prop in obj +} + +function getElementDisplayName(element: Element) { const value = getElementValue(element) - const hasChecked = element.type === 'checkbox' || element.type === 'radio' + const hasChecked = + isElementType(element, 'input', {type: 'checkbox'}) || + isElementType(element, 'input', {type: 'radio'}) return [ element.tagName.toLowerCase(), element.id ? `#${element.id}` : null, - element.name ? `[name="${element.name}"]` : null, - element.htmlFor ? `[for="${element.htmlFor}"]` : null, + hasProperty(element, 'name') && element.name + ? `[name="${element.name}"]` + : null, + hasProperty(element, 'htmlFor') && element.htmlFor + ? `[for="${element.htmlFor}"]` + : null, value ? `[value=${value}]` : null, hasChecked ? `[checked=${element.checked}]` : null, isElementType(element, 'option') ? `[selected=${element.selected}]` : null, @@ -169,13 +219,44 @@ function getElementDisplayName(element) { .join('') } -function addListeners(element, {eventHandlers = {}} = {}) { - const eventHandlerCalls = {current: []} +type CallData = { + event: Event + elementDisplayName: string + testData?: TestData +} + +type TestData = { + handled?: boolean + + // Where is this assigned? + before?: Element + after?: Element +} + +function isElement(target: EventTarget): target is Element { + return 'tagName' in target +} + +function isMouseEvent(event: Event): event is MouseEvent { + return event.constructor.name === 'MouseEvent' +} + +function addListeners( + element: Element & {testData?: TestData}, + { + eventHandlers = {}, + }: { + eventHandlers?: EventHandlers + } = {}, +) { + const eventHandlerCalls: {current: CallData[]} = {current: []} const generalListener = jest - .fn(event => { - const callData = { + .fn((event: Event) => { + const target = event.target + const callData: CallData = { event, - elementDisplayName: getElementDisplayName(event.target), + elementDisplayName: + target && isElement(target) ? getElementDisplayName(target) : '', } if (element.testData && !element.testData.handled) { callData.testData = element.testData @@ -192,10 +273,9 @@ function addListeners(element, {eventHandlers = {}} = {}) { for (const name of listeners) { addEventListener(element, name.toLowerCase(), (...args) => { - const handler = eventHandlers[name] - if (handler) { + if (name in eventHandlers) { generalListener(...args) - return handler(...args) + return eventHandlers[name](...args) } return generalListener(...args) }) @@ -208,10 +288,15 @@ function addListeners(element, {eventHandlers = {}} = {}) { function getEventSnapshot() { const eventCalls = eventHandlerCalls.current .map(({event, testData, elementDisplayName}) => { + const eventName = event.constructor.name const eventLabel = - eventLabelGetters[event.constructor.name]?.(event) ?? '' + eventName in eventLabelGetters + ? eventLabelGetters[eventName as keyof typeof eventLabelGetters]( + event as KeyboardEvent & MouseEvent, + ) + : '' const modifiers = ['altKey', 'shiftKey', 'metaKey', 'ctrlKey'] - .filter(key => event[key]) + .filter(key => event[key as keyof Event]) .map(k => `{${k.replace('Key', '')}}`) .join('') @@ -245,18 +330,17 @@ function addListeners(element, {eventHandlers = {}} = {}) { generalListener.mockClear() eventHandlerCalls.current = [] } - const getEvents = type => + const getEvents = (type?: string) => generalListener.mock.calls .map(([e]) => e) .filter(e => !type || e.type === type) - const eventWasFired = eventType => getEvents().some(e => e.type === eventType) + const eventWasFired = (eventType: string) => getEvents(eventType).length > 0 function getClickEventsSnapshot() { - const lines = getEvents().map( - ({constructor, type, button, buttons, detail}) => - constructor.name === 'MouseEvent' - ? `${type} - button=${button}; buttons=${buttons}; detail=${detail}` - : type, + const lines = getEvents().map(e => + isMouseEvent(e) + ? `${e.type} - button=${e.button}; buttons=${e.buttons}; detail=${e.detail}` + : e.type, ) return {snapshot: lines.join('\n')} } @@ -270,21 +354,23 @@ function addListeners(element, {eventHandlers = {}} = {}) { } } -function getValueWithSelection({value, selectionStart, selectionEnd}) { +function getValueWithSelection(element?: Element) { + const {value, selectionStart, selectionEnd} = element as HTMLInputElement + return [ - value.slice(0, selectionStart), + value.slice(0, selectionStart ?? undefined), ...(selectionStart === selectionEnd ? ['{CURSOR}'] : [ '{SELECTION}', - value.slice(selectionStart, selectionEnd), + value.slice(selectionStart ?? 0, selectionEnd ?? undefined), '{/SELECTION}', ]), - value.slice(selectionEnd), + value.slice(selectionEnd ?? undefined), ].join('') } -const changeLabelGetter = { +const changeLabelGetter: Record<PropertyKey, (d: TestData) => string> = { value: ({before, after}) => [ JSON.stringify(getValueWithSelection(before)), @@ -292,8 +378,8 @@ const changeLabelGetter = { ].join(' -> '), checked: ({before, after}) => [ - before.checked ? 'checked' : 'unchecked', - after.checked ? 'checked' : 'unchecked', + (before as HTMLInputElement).checked ? 'checked' : 'unchecked', + (after as HTMLInputElement).checked ? 'checked' : 'unchecked', ].join(' -> '), // unfortunately, changing a select option doesn't happen within fireEvent @@ -303,16 +389,28 @@ const changeLabelGetter = { } changeLabelGetter.selectionStart = changeLabelGetter.value changeLabelGetter.selectionEnd = changeLabelGetter.value -const getDefaultLabel = ({key, before, after}) => - `${key}: ${JSON.stringify(before[key])} -> ${JSON.stringify(after[key])}` -function getChanges({before, after}) { +const getDefaultLabel = <T>({ + key, + before, + after, +}: { + key: keyof T + before: T + after: T +}) => `${key}: ${JSON.stringify(before[key])} -> ${JSON.stringify(after[key])}` + +function getChanges({before, after}: TestData) { const changes = new Set() - for (const key of Object.keys(before)) { - if (after[key] !== before[key]) { - changes.add( - (changeLabelGetter[key] ?? getDefaultLabel)({key, before, after}), - ) + if (before && after) { + for (const key of Object.keys(before) as Array<keyof typeof before>) { + if (after[key] !== before[key]) { + changes.add( + (key in changeLabelGetter ? changeLabelGetter[key] : getDefaultLabel)( + {key, before, after}, + ), + ) + } } } diff --git a/src/__tests__/keyboard/index.ts b/src/__tests__/keyboard/index.ts index 4b573940..3eacd272 100644 --- a/src/__tests__/keyboard/index.ts +++ b/src/__tests__/keyboard/index.ts @@ -26,7 +26,7 @@ it('type without focus', () => { it('type with focus', () => { const {element} = setup('<input/>') const {getEventSnapshot} = addListeners(document.body) - ;(element as HTMLInputElement).focus() + element.focus() userEvent.keyboard('foo') @@ -53,7 +53,7 @@ it('type with focus', () => { it('type asynchronous', async () => { const {element} = setup('<input/>') const {getEventSnapshot} = addListeners(document.body) - ;(element as HTMLInputElement).focus() + element.focus() // eslint-disable-next-line testing-library/no-await-sync-events await userEvent.keyboard('foo', {delay: 1}) @@ -110,7 +110,7 @@ describe('error', () => { it('continue typing with state', () => { const {element, getEventSnapshot, clearEventCalls} = setup('<input/>') - ;(element as HTMLInputElement).focus() + element.focus() clearEventCalls() const state = userEvent.keyboard('[ShiftRight>]') diff --git a/src/__tests__/keyboard/keyboardImplementation.ts b/src/__tests__/keyboard/keyboardImplementation.ts index ef3b4f1b..be9d8329 100644 --- a/src/__tests__/keyboard/keyboardImplementation.ts +++ b/src/__tests__/keyboard/keyboardImplementation.ts @@ -3,7 +3,7 @@ import {setup} from '../helpers/utils' test('no character input if `altKey` or `ctrlKey` is pressed', () => { const {element, eventWasFired} = setup(`<input/>`) - ;(element as HTMLInputElement).focus() + element.focus() userEvent.keyboard('[ControlLeft>]g') diff --git a/src/__tests__/keyboard/plugin/arrow.ts b/src/__tests__/keyboard/plugin/arrow.ts index 3dea28c1..009744ab 100644 --- a/src/__tests__/keyboard/plugin/arrow.ts +++ b/src/__tests__/keyboard/plugin/arrow.ts @@ -2,7 +2,7 @@ import userEvent from 'index' import {setup} from '__tests__/helpers/utils' const setupInput = () => - setup(`<input value="foobar"/>`).element as HTMLInputElement + setup<HTMLInputElement>(`<input value="foobar"/>`).element test('collapse selection to the left', () => { const el = setupInput() diff --git a/src/__tests__/keyboard/plugin/character.ts b/src/__tests__/keyboard/plugin/character.ts index 424c68f1..c8b6b1f5 100644 --- a/src/__tests__/keyboard/plugin/character.ts +++ b/src/__tests__/keyboard/plugin/character.ts @@ -4,10 +4,7 @@ import {setup} from '__tests__/helpers/utils' test('type [Enter] in textarea', () => { const {element, getEvents} = setup(`<textarea>f</textarea>`) - userEvent.type( - element as HTMLTextAreaElement, - 'oo[Enter]bar[ShiftLeft>][Enter]baz', - ) + userEvent.type(element, 'oo[Enter]bar[ShiftLeft>][Enter]baz') expect(element).toHaveValue('foo\nbar\nbaz') expect(getEvents('input')[2]).toHaveProperty('inputType', 'insertLineBreak') @@ -16,12 +13,12 @@ test('type [Enter] in textarea', () => { test('type [Enter] in contenteditable', () => { const {element, getEvents} = setup(`<div contenteditable="true">f</div>`) - ;(element as HTMLDivElement).focus() + element.focus() userEvent.keyboard('oo[Enter]bar[ShiftLeft>][Enter]baz') expect(element).toHaveTextContent('foo bar baz') - expect(element?.firstChild).toHaveProperty('nodeValue', 'foo\nbar\nbaz') + expect(element.firstChild).toHaveProperty('nodeValue', 'foo\nbar\nbaz') expect(getEvents('input')[2]).toHaveProperty('inputType', 'insertParagraph') expect(getEvents('input')[6]).toHaveProperty('inputType', 'insertLineBreak') }) @@ -36,7 +33,7 @@ test.each([ 'type invalid values into <input type="number"/>', (text, expectedValue, expectedCarryValue, expectedInputEvents) => { const {element, getEvents} = setup(`<input type="number"/>`) - ;(element as HTMLInputElement).focus() + element.focus() const state = userEvent.keyboard(text) diff --git a/src/__tests__/keyboard/plugin/control.ts b/src/__tests__/keyboard/plugin/control.ts index 224bcf6f..99699fa4 100644 --- a/src/__tests__/keyboard/plugin/control.ts +++ b/src/__tests__/keyboard/plugin/control.ts @@ -2,10 +2,12 @@ import userEvent from 'index' import {setup} from '__tests__/helpers/utils' test('press [Home] in textarea', () => { - const {element} = setup(`<textarea>foo\nbar\baz</textarea>`) - ;(element as HTMLTextAreaElement).setSelectionRange(2, 4) + const {element} = setup<HTMLTextAreaElement>( + `<textarea>foo\nbar\baz</textarea>`, + ) + element.setSelectionRange(2, 4) - userEvent.type(element as HTMLTextAreaElement, '[Home]') + userEvent.type(element, '[Home]') expect(element).toHaveProperty('selectionStart', 0) expect(element).toHaveProperty('selectionEnd', 0) @@ -13,22 +15,22 @@ test('press [Home] in textarea', () => { test('press [Home] in contenteditable', () => { const {element} = setup(`<div contenteditable="true">foo\nbar\baz</div>`) - document - .getSelection() - ?.setPosition((element as HTMLDivElement).firstChild, 2) + document.getSelection()?.setPosition(element.firstChild, 2) - userEvent.type(element as HTMLTextAreaElement, '[Home]') + userEvent.type(element, '[Home]') const selection = document.getSelection() - expect(selection).toHaveProperty('focusNode', element?.firstChild) + expect(selection).toHaveProperty('focusNode', element.firstChild) expect(selection).toHaveProperty('focusOffset', 0) }) test('press [End] in textarea', () => { - const {element} = setup(`<textarea>foo\nbar\baz</textarea>`) - ;(element as HTMLTextAreaElement).setSelectionRange(2, 4) + const {element} = setup<HTMLTextAreaElement>( + `<textarea>foo\nbar\baz</textarea>`, + ) + element.setSelectionRange(2, 4) - userEvent.type(element as HTMLTextAreaElement, '[End]') + userEvent.type(element, '[End]') expect(element).toHaveProperty('selectionStart', 10) expect(element).toHaveProperty('selectionEnd', 10) @@ -36,14 +38,12 @@ test('press [End] in textarea', () => { test('press [End] in contenteditable', () => { const {element} = setup(`<div contenteditable="true">foo\nbar\baz</div>`) - document - .getSelection() - ?.setPosition((element as HTMLDivElement).firstChild, 2) + document.getSelection()?.setPosition(element.firstChild, 2) - userEvent.type(element as HTMLTextAreaElement, '[End]') + userEvent.type(element, '[End]') const selection = document.getSelection() - expect(selection).toHaveProperty('focusNode', element?.firstChild) + expect(selection).toHaveProperty('focusNode', element.firstChild) expect(selection).toHaveProperty('focusOffset', 10) }) @@ -51,7 +51,7 @@ test('use [Delete] on number input', () => { const {element} = setup(`<input type="number"/>`) userEvent.type( - element as HTMLInputElement, + element, '1e-5[ArrowLeft][Delete]6[ArrowLeft][ArrowLeft][ArrowLeft][Delete][Delete]', ) diff --git a/src/__tests__/keyboard/plugin/functional.ts b/src/__tests__/keyboard/plugin/functional.ts index 51047b26..cc72f8e0 100644 --- a/src/__tests__/keyboard/plugin/functional.ts +++ b/src/__tests__/keyboard/plugin/functional.ts @@ -32,7 +32,7 @@ test('produce extra events for the Control key when AltGraph is pressed', () => test('backspace to valid value', () => { const {element, getEventSnapshot} = setup(`<input type="number"/>`) - userEvent.type(element as Element, '5e-[Backspace][Backspace]') + userEvent.type(element, '5e-[Backspace][Backspace]') expect(element).toHaveValue(5) expect(getEventSnapshot()).toMatchInlineSnapshot(` @@ -76,7 +76,7 @@ test('trigger click event on [Enter] keydown on HTMLAnchorElement', () => { const {element, getEventSnapshot, getEvents} = setup( `<a href="example.com" target="_blank"/>`, ) - ;(element as HTMLAnchorElement).focus() + element.focus() userEvent.keyboard('[Enter]') @@ -99,7 +99,7 @@ test('trigger click event on [Enter] keydown on HTMLAnchorElement', () => { test('trigger click event on [Enter] keypress on HTMLButtonElement', () => { const {element, getEventSnapshot, getEvents} = setup(`<button/>`) - ;(element as HTMLButtonElement).focus() + element.focus() userEvent.keyboard('[Enter]') @@ -119,7 +119,7 @@ test('trigger click event on [Enter] keypress on HTMLButtonElement', () => { test('trigger click event on [Space] keyup on HTMLButtonElement', () => { const {element, getEventSnapshot, getEvents} = setup(`<button/>`) - ;(element as HTMLButtonElement).focus() + element.focus() userEvent.keyboard('[Space]') @@ -138,8 +138,10 @@ test('trigger click event on [Space] keyup on HTMLButtonElement', () => { }) test('trigger click event on [Space] keyup on HTMLInputElement type=button', () => { - const {element, getEventSnapshot, getEvents} = setup(`<input type="button" />`) - ;(element as HTMLButtonElement).focus() + const {element, getEventSnapshot, getEvents} = setup( + `<input type="button" />`, + ) + element.focus() userEvent.keyboard('[Space]') @@ -159,7 +161,7 @@ test('trigger click event on [Space] keyup on HTMLInputElement type=button', () test('trigger change event on [Space] keyup on HTMLInputElement type=radio', () => { const {element, getEventSnapshot, getEvents} = setup(`<input type="radio" />`) - ;(element as HTMLInputElement).focus() + element.focus() userEvent.keyboard('[Space]') diff --git a/src/__tests__/keyboard/shared/fireInputEvent.ts b/src/__tests__/keyboard/shared/fireInputEvent.ts index 1570f5bb..e5adfac9 100644 --- a/src/__tests__/keyboard/shared/fireInputEvent.ts +++ b/src/__tests__/keyboard/shared/fireInputEvent.ts @@ -4,9 +4,9 @@ import userEvent from '../../../' it('dispatch change event on blur', () => { const {element, getEvents} = setup('<input/>') - ;(element as HTMLInputElement).focus() + element.focus() userEvent.keyboard('foo') - ;(element as HTMLInputElement).blur() + element.blur() expect(getEvents('change')).toHaveLength(1) }) @@ -14,10 +14,10 @@ it('dispatch change event on blur', () => { it('do not dispatch change event if value did not change', () => { const {element, getEvents} = setup('<input/>') - ;(element as HTMLInputElement).focus() + element.focus() userEvent.keyboard('foo') userEvent.keyboard('{backspace}{backspace}{backspace}') - ;(element as HTMLInputElement).blur() + element.blur() expect(getEvents('change')).toHaveLength(0) }) diff --git a/src/__tests__/utils/edit/calculateNewValue.ts b/src/__tests__/utils/edit/calculateNewValue.ts index 92dc0bdb..79eb4a6b 100644 --- a/src/__tests__/utils/edit/calculateNewValue.ts +++ b/src/__tests__/utils/edit/calculateNewValue.ts @@ -5,7 +5,7 @@ import {setup} from '__tests__/helpers/utils' test('honors maxlength', () => { const {element, getEventSnapshot} = setup('<input maxlength="2" />') - userEvent.type(element as Element, '123') + userEvent.type(element, '123') // NOTE: no input event when typing "3" expect(getEventSnapshot()).toMatchInlineSnapshot(` @@ -40,7 +40,7 @@ test('honors maxlength', () => { test('honors maxlength="" as if there was no maxlength', () => { const {element, getEventSnapshot} = setup('<input maxlength="" />') - userEvent.type(element as Element, '123') + userEvent.type(element, '123') expect(getEventSnapshot()).toMatchInlineSnapshot(` Events fired on: input[value="123"] @@ -77,7 +77,7 @@ test('honors maxlength with existing text', () => { const {element, getEventSnapshot} = setup( '<input value="12" maxlength="2" />', ) - userEvent.type(element as Element, '3') + userEvent.type(element, '3') // NOTE: no input event when typing "3" expect(getEventSnapshot()).toMatchInlineSnapshot(` @@ -108,7 +108,7 @@ test('honors maxlength on textarea', () => { '<textarea maxlength="2">12</textarea>', ) - userEvent.type(element as Element, '3') + userEvent.type(element, '3') expect(getEventSnapshot()).toMatchInlineSnapshot(` Events fired on: textarea[value="12"] @@ -137,7 +137,7 @@ test('honors maxlength on textarea', () => { test('ignores maxlength on input[type=number]', () => { const {element} = setup(`<input maxlength="2" type="number" value="12" />`) - userEvent.type(element as Element, '3') + userEvent.type(element, '3') expect(element).toHaveValue(123) }) diff --git a/src/__tests__/utils/edit/selectionRange.ts b/src/__tests__/utils/edit/selectionRange.ts index dda87b42..2e6f4315 100644 --- a/src/__tests__/utils/edit/selectionRange.ts +++ b/src/__tests__/utils/edit/selectionRange.ts @@ -4,25 +4,25 @@ import {setup} from '__tests__/helpers/utils' test('range on input', () => { const {element} = setup('<input value="foo"/>') - expect(getSelectionRange(element as HTMLInputElement)).toEqual({ + expect(getSelectionRange(element)).toEqual({ selectionStart: 0, selectionEnd: 0, }) - setSelectionRange(element as HTMLInputElement, 0, 0) + setSelectionRange(element, 0, 0) expect(element).toHaveProperty('selectionStart', 0) expect(element).toHaveProperty('selectionEnd', 0) - expect(getSelectionRange(element as HTMLInputElement)).toEqual({ + expect(getSelectionRange(element)).toEqual({ selectionStart: 0, selectionEnd: 0, }) - setSelectionRange(element as HTMLInputElement, 2, 3) + setSelectionRange(element, 2, 3) expect(element).toHaveProperty('selectionStart', 2) expect(element).toHaveProperty('selectionEnd', 3) - expect(getSelectionRange(element as HTMLInputElement)).toEqual({ + expect(getSelectionRange(element)).toEqual({ selectionStart: 2, selectionEnd: 3, }) @@ -31,25 +31,25 @@ test('range on input', () => { test('range on contenteditable', () => { const {element} = setup('<div contenteditable="true">foo</div>') - expect(getSelectionRange(element as HTMLInputElement)).toEqual({ + expect(getSelectionRange(element)).toEqual({ selectionStart: null, selectionEnd: null, }) - setSelectionRange(element as HTMLDivElement, 0, 0) + setSelectionRange(element, 0, 0) - expect(getSelectionRange(element as HTMLInputElement)).toEqual({ + expect(getSelectionRange(element)).toEqual({ selectionStart: 0, selectionEnd: 0, }) - setSelectionRange(element as HTMLDivElement, 2, 3) + setSelectionRange(element, 2, 3) - expect(document.getSelection()?.anchorNode).toBe(element?.firstChild) - expect(document.getSelection()?.focusNode).toBe(element?.firstChild) + expect(document.getSelection()?.anchorNode).toBe(element.firstChild) + expect(document.getSelection()?.focusNode).toBe(element.firstChild) expect(document.getSelection()?.anchorOffset).toBe(2) expect(document.getSelection()?.focusOffset).toBe(3) - expect(getSelectionRange(element as HTMLInputElement)).toEqual({ + expect(getSelectionRange(element)).toEqual({ selectionStart: 2, selectionEnd: 3, }) @@ -58,14 +58,14 @@ test('range on contenteditable', () => { test('range on input without selection support', () => { const {element} = setup(`<input type="number" value="123"/>`) - expect(getSelectionRange(element as HTMLInputElement)).toEqual({ + expect(getSelectionRange(element)).toEqual({ selectionStart: null, selectionEnd: null, }) - setSelectionRange(element as HTMLInputElement, 1, 2) + setSelectionRange(element, 1, 2) - expect(getSelectionRange(element as HTMLInputElement)).toEqual({ + expect(getSelectionRange(element)).toEqual({ selectionStart: 1, selectionEnd: 2, }) diff --git a/src/__tests__/utils/misc/hasPointerEvents.ts b/src/__tests__/utils/misc/hasPointerEvents.ts index d7592683..0b292822 100644 --- a/src/__tests__/utils/misc/hasPointerEvents.ts +++ b/src/__tests__/utils/misc/hasPointerEvents.ts @@ -10,8 +10,8 @@ test('get pointer-events from element or ancestor', () => { </div> `) - expect(hasPointerEvents(element as HTMLDivElement)).toBe(false) - expect(hasPointerEvents((element as HTMLDivElement).children[0])).toBe(true) - expect(hasPointerEvents((element as HTMLDivElement).children[1])).toBe(false) - expect(hasPointerEvents((element as HTMLDivElement).children[2])).toBe(false) + expect(hasPointerEvents(element)).toBe(false) + expect(hasPointerEvents(element.children[0])).toBe(true) + expect(hasPointerEvents(element.children[1])).toBe(false) + expect(hasPointerEvents(element.children[2])).toBe(false) })