From 77a7fa840a162e1361fab88e52cb01b3c805163a Mon Sep 17 00:00:00 2001 From: Philipp Fritsche Date: Fri, 15 Jul 2022 11:30:10 +0200 Subject: [PATCH] fix(document): do not track `value` on `HTMLSelectElement` (#989) * fix(document): do not track `value` on `HTMLSelectElement` * throw error when trying to track non-existent property --- src/document/index.ts | 7 ++++--- src/document/interceptor.ts | 7 +++++-- src/document/value.ts | 4 +++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/document/index.ts b/src/document/index.ts index 9d63fa19..7ca2a2b3 100644 --- a/src/document/index.ts +++ b/src/document/index.ts @@ -1,5 +1,6 @@ import {dispatchUIEvent} from '../event' import {Config} from '../setup' +import {isElementType} from '../utils' import {prepareSelectionInterceptor} from './selection' import {prepareRangeTextInterceptor} from './setRangeText' import { @@ -24,7 +25,7 @@ export function prepareDocument(document: Document) { document.addEventListener( 'focus', e => { - const el = e.target as Node + const el = e.target as Element prepareElement(el) }, @@ -62,12 +63,12 @@ export function prepareDocument(document: Document) { document[isPrepared] = isPrepared } -function prepareElement(el: Node | HTMLInputElement) { +function prepareElement(el: Element) { if (el[isPrepared]) { return } - if ('value' in el) { + if (isElementType(el, ['input', 'textarea'])) { prepareValueInterceptor(el) prepareSelectionInterceptor(el) prepareRangeTextInterceptor(el) diff --git a/src/document/interceptor.ts b/src/document/interceptor.ts index d5fe4efc..2fe1977b 100644 --- a/src/document/interceptor.ts +++ b/src/document/interceptor.ts @@ -10,7 +10,7 @@ type Params = Prop extends anyFunc ? Parameters : [Prop] type ImplReturn = Prop extends anyFunc ? Parameters : Prop export function prepareInterceptor< - ElementType extends Node, + ElementType extends Element, PropName extends keyof ElementType, >( element: ElementType, @@ -39,11 +39,14 @@ export function prepareInterceptor< const target = prototypeDescriptor?.set ? 'set' : 'value' + /* istanbul ignore if */ if ( typeof prototypeDescriptor?.[target] !== 'function' || (prototypeDescriptor[target] as Interceptable)[Interceptor] ) { - return + throw new Error( + `Element ${element.tagName} does not implement "${String(propName)}".`, + ) } function intercept( diff --git a/src/document/value.ts b/src/document/value.ts index dd04024c..53959f40 100644 --- a/src/document/value.ts +++ b/src/document/value.ts @@ -57,7 +57,9 @@ function sanitizeValue( return String(v) } -export function prepareValueInterceptor(element: HTMLInputElement) { +export function prepareValueInterceptor( + element: HTMLInputElement | HTMLTextAreaElement, +) { prepareInterceptor(element, 'value', valueInterceptor) }