Skip to content

Commit

Permalink
fix(document): use setters/methods on element as default (#987)
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche authored Jul 14, 2022
1 parent 29bdf14 commit c40e614
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/document/interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function prepareInterceptor<
...args: Params<ElementType[PropName]>
) {
const {
applyNative = true,
applyNative = false,
realArgs,
then,
} = interceptorImpl.call(this, ...args)
Expand Down
8 changes: 4 additions & 4 deletions src/document/selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ export function prepareSelectionInterceptor(
function interceptorImpl(
this: HTMLInputElement | HTMLTextAreaElement,
start: number | Value | null,
end: number | null,
direction: 'forward' | 'backward' | 'none' = 'none',
...others
) {
const isUI = start && typeof start === 'object' && start[UISelection]

Expand All @@ -42,10 +41,11 @@ export function prepareSelectionInterceptor(
}

return {
realArgs: [Number(start), end, direction] as [
applyNative: !!isUI,
realArgs: [Number(start), ...others] as [
number,
number,
typeof direction,
'forward' | 'backward' | 'none' | undefined,
],
}
},
Expand Down
42 changes: 42 additions & 0 deletions tests/document/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,45 @@ test('track changes to value and selection per setRangeText', () => {
expect(getUIValue(element)).toBe('aYcd')
expect(getUISelection(element)).toHaveProperty('focusOffset', 1)
})

test('circumvent setters/methods for UI changes', () => {
const {element} = render<HTMLInputElement>(`<input/>`, {focus: false})

const prototypeDescr = Object.getOwnPropertyDescriptors<HTMLInputElement>(
Object.getPrototypeOf(element) as HTMLInputElement,
)
const valueSpy = jest.fn(prototypeDescr.value.set)
const setSelectionRangeSpy = jest.fn(prototypeDescr.setSelectionRange.value)

Object.defineProperties(element, {
value: {
get: () => {
throw new Error()
},
...prototypeDescr.value,
set: valueSpy,
},
setSelectionRange: {
...prototypeDescr.setSelectionRange,
value: setSelectionRangeSpy,
},
})

prepare(element)
element.focus()

setUIValue(element, 'abcd')
setUISelection(element, {focusOffset: 3})

expect(element).toHaveValue('abcd')
expect(element).toHaveProperty('selectionStart', 3)
expect(valueSpy).not.toBeCalled()
expect(setSelectionRangeSpy).not.toBeCalled()

element.value = 'efgh'
element.setSelectionRange(1, 2)
expect(element).toHaveValue('efgh')
expect(element).toHaveProperty('selectionStart', 1)
expect(valueSpy).toBeCalledWith('efgh')
expect(setSelectionRangeSpy).toBeCalledWith(1, 2)
})

0 comments on commit c40e614

Please sign in to comment.