diff --git a/src/document/interceptor.ts b/src/document/interceptor.ts index 4ff51e11..6d6ecc2f 100644 --- a/src/document/interceptor.ts +++ b/src/document/interceptor.ts @@ -28,6 +28,7 @@ export function prepareInterceptor< */ applyNative?: boolean realArgs?: ImplReturn + then?: () => void }, ) { const prototypeDescriptor = Object.getOwnPropertyDescriptor( @@ -49,7 +50,11 @@ export function prepareInterceptor< this: ElementType, ...args: Params ) { - const {applyNative = true, realArgs} = interceptorImpl.call(this, ...args) + const { + applyNative = true, + realArgs, + then, + } = interceptorImpl.call(this, ...args) const realFunc = ((!applyNative && objectDescriptor) || (prototypeDescriptor as PropertyDescriptor))[target] as ( @@ -62,6 +67,8 @@ export function prepareInterceptor< } else { realFunc.call(this, ...realArgs) } + + then?.() } ;(intercept as Interceptable)[Interceptor] = Interceptor diff --git a/src/document/value.ts b/src/document/value.ts index c91a85c1..b55a9b4b 100644 --- a/src/document/value.ts +++ b/src/document/value.ts @@ -32,13 +32,12 @@ function valueInterceptor( if (isUI) { this[UIValue] = String(v) setPreviousValue(this, String(this.value)) - } else { - trackOrSetValue(this, String(v)) } return { applyNative: !!isUI, realArgs: sanitizeValue(this, v), + then: isUI ? undefined : () => trackOrSetValue(this, String(v)), } } diff --git a/tests/document/index.ts b/tests/document/index.ts index 72c68603..28412c4e 100644 --- a/tests/document/index.ts +++ b/tests/document/index.ts @@ -112,6 +112,20 @@ test('maintain selection range on elements without support for selection range', expect(element.selectionStart).toBe(null) }) +test('reset UI selection if value is programmatically set', async () => { + const {element} = render(``) + + prepare(element) + + setUIValue(element, 'abc') + setUISelection(element, {anchorOffset: 1, focusOffset: 2}) + + element.value = 'abcdef' + expect(element.selectionStart).toBe(6) + expect(getUISelection(element)).toHaveProperty('focusOffset', 6) + expect(getUISelection(element)).toHaveProperty('startOffset', 6) +}) + test('clear UI selection if selection is programmatically set', async () => { const {element} = render(``)