From 2b0632ab7d1cf6db72eba4d8116f57e95c567260 Mon Sep 17 00:00:00 2001 From: Philipp Fritsche Date: Tue, 23 Mar 2021 14:42:27 +0100 Subject: [PATCH] fix(keyboard): inputType for Enter on contenteditable (#614) * fix: getSelectionRange on contenteditable without Range * fix: inputType for `Enter` on contenteditable * test: bump coverage --- src/__tests__/keyboard/plugin/character.ts | 22 +++++++++++++++------- src/keyboard/plugins/character.ts | 9 +++++++-- src/utils/edit/getSelectionRange.ts | 5 ++--- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/__tests__/keyboard/plugin/character.ts b/src/__tests__/keyboard/plugin/character.ts index 095acea1..fc85af18 100644 --- a/src/__tests__/keyboard/plugin/character.ts +++ b/src/__tests__/keyboard/plugin/character.ts @@ -2,18 +2,26 @@ import userEvent from 'index' import {setup} from '__tests__/helpers/utils' test('type [Enter] in textarea', () => { - const {element} = setup(``) + const {element, getEvents} = setup(``) - userEvent.type(element as HTMLTextAreaElement, 'oo[Enter]bar') + userEvent.type( + element as HTMLTextAreaElement, + 'oo[Enter]bar[ShiftLeft>][Enter]baz', + ) - expect(element).toHaveValue('foo\nbar') + expect(element).toHaveValue('foo\nbar\nbaz') + expect(getEvents('input')[2]).toHaveProperty('inputType', 'insertLineBreak') + expect(getEvents('input')[6]).toHaveProperty('inputType', 'insertLineBreak') }) test('type [Enter] in contenteditable', () => { - const {element} = setup(`
f
`) + const {element, getEvents} = setup(`
f
`) + ;(element as HTMLDivElement).focus() - userEvent.type(element as HTMLTextAreaElement, 'oo[Enter]bar') + userEvent.keyboard('oo[Enter]bar[ShiftLeft>][Enter]baz') - expect(element).toHaveTextContent('foo bar') - expect(element?.firstChild).toHaveProperty('nodeValue', 'foo\nbar') + expect(element).toHaveTextContent('foo bar baz') + expect(element?.firstChild).toHaveProperty('nodeValue', 'foo\nbar\nbaz') + expect(getEvents('input')[2]).toHaveProperty('inputType', 'insertParagraph') + expect(getEvents('input')[6]).toHaveProperty('inputType', 'insertLineBreak') }) diff --git a/src/keyboard/plugins/character.ts b/src/keyboard/plugins/character.ts index 31d523d6..f8ca9856 100644 --- a/src/keyboard/plugins/character.ts +++ b/src/keyboard/plugins/character.ts @@ -165,17 +165,22 @@ export const keypressBehavior: behaviorPlugin[] = [ keyDef.key === 'Enter' && (isInstanceOfElement(element, 'HTMLTextAreaElement') || isContentEditable(element)), - handle: (keyDef, element) => { + handle: (keyDef, element, options, state) => { const {newValue, newSelectionStart} = calculateNewValue( '\n', element as HTMLElement, ) + const inputType = + isContentEditable(element) && !state.modifiers.shift + ? 'insertParagraph' + : 'insertLineBreak' + fireInputEventIfNeeded({ newValue, newSelectionStart, eventOverrides: { - inputType: 'insertLineBreak', + inputType, }, currentElement: () => element, }) diff --git a/src/utils/edit/getSelectionRange.ts b/src/utils/edit/getSelectionRange.ts index 7d8476f6..6094001a 100644 --- a/src/utils/edit/getSelectionRange.ts +++ b/src/utils/edit/getSelectionRange.ts @@ -8,10 +8,9 @@ export function getSelectionRange( } { if (isContentEditable(element)) { const selection = element.ownerDocument.getSelection() - const range = selection?.getRangeAt(0) - // istanbul ignore else - if (range) { + if (selection?.rangeCount) { + const range = selection.getRangeAt(0) return { selectionStart: range.startOffset, selectionEnd: range.endOffset,