diff --git a/__tests__/react/click.js b/__tests__/react/click.js index 6136919e..865b6968 100644 --- a/__tests__/react/click.js +++ b/__tests__/react/click.js @@ -198,6 +198,92 @@ describe("userEvent.click", () => { expect(b).toHaveFocus(); }); + it("should not blur when mousedown prevents default", () => { + let events = []; + const eventsHandler = jest.fn(evt => events.push(evt.type)); + const commonEvents = { + onBlur: eventsHandler, + onMouseOver: eventsHandler, + onMouseMove: eventsHandler, + onMouseDown: eventsHandler, + onFocus: eventsHandler, + onMouseUp: eventsHandler, + onClick: eventsHandler, + onChange: eventsHandler + }; + + const { getByTestId } = render( + + + { + e.preventDefault(); + eventsHandler(e); + }} + /> + + + ); + + const a = getByTestId("A"); + const b = getByTestId("B"); + const c = getByTestId("C"); + + expect(a).not.toHaveFocus(); + expect(b).not.toHaveFocus(); + expect(c).not.toHaveFocus(); + + userEvent.click(a); + expect(a).toHaveFocus(); + expect(b).not.toHaveFocus(); + expect(c).not.toHaveFocus(); + + expect(events).toEqual([ + "mouseover", + "mousemove", + "mousedown", + "focus", + "mouseup", + "click" + ]); + + events = []; + + userEvent.click(b); + expect(a).toHaveFocus(); + expect(b).not.toHaveFocus(); + expect(c).not.toHaveFocus(); + + expect(events).toEqual([ + "mousemove", + "mouseover", + "mousemove", + "mousedown", + "mouseup", + "click" + ]); + + events = []; + + userEvent.click(c); + expect(a).not.toHaveFocus(); + expect(b).not.toHaveFocus(); + expect(c).toHaveFocus(); + + expect(events).toEqual([ + "mousemove", + "mouseover", + "mousemove", + "mousedown", + "blur", + "focus", + "mouseup", + "click" + ]); + }); + it("does not lose focus when click updates focus", () => { const FocusComponent = () => { const inputRef = React.useRef(); @@ -328,9 +414,9 @@ describe("userEvent.click", () => { const { getByTestId } = render( React.createElement(type, { "data-testid": "element", - onMouseDown: (evt) => { + onMouseDown: evt => { evt.preventDefault(); - }, + } }) ); diff --git a/__tests__/react/dblclick.js b/__tests__/react/dblclick.js index a1049323..655482d2 100644 --- a/__tests__/react/dblclick.js +++ b/__tests__/react/dblclick.js @@ -104,4 +104,99 @@ describe("userEvent.dblClick", () => { "click" ]); }); + + it("should not blur when mousedown prevents default", () => { + let events = []; + const eventsHandler = jest.fn(evt => events.push(evt.type)); + const commonEvents = { + onBlur: eventsHandler, + onMouseOver: eventsHandler, + onMouseMove: eventsHandler, + onMouseDown: eventsHandler, + onFocus: eventsHandler, + onMouseUp: eventsHandler, + onClick: eventsHandler, + onChange: eventsHandler + }; + + const { getByTestId } = render( + + + { + e.preventDefault(); + eventsHandler(e); + }} + /> + + + ); + + const a = getByTestId("A"); + const b = getByTestId("B"); + const c = getByTestId("C"); + + expect(a).not.toHaveFocus(); + expect(b).not.toHaveFocus(); + expect(c).not.toHaveFocus(); + + userEvent.dblClick(a); + expect(a).toHaveFocus(); + expect(b).not.toHaveFocus(); + expect(c).not.toHaveFocus(); + + expect(events).toEqual([ + "mouseover", + "mousemove", + "mousedown", + "focus", + "mouseup", + "click", + "mousedown", + "mouseup", + "click" + ]); + + events = []; + + userEvent.dblClick(b); + expect(a).toHaveFocus(); + expect(b).not.toHaveFocus(); + expect(c).not.toHaveFocus(); + + expect(events).toEqual([ + "mousemove", + "mouseover", + "mousemove", + "mousedown", + "mouseup", + "click", + "mousedown", + "mouseup", + "click" + ]); + + events = []; + + userEvent.dblClick(c); + expect(a).not.toHaveFocus(); + expect(b).not.toHaveFocus(); + expect(c).toHaveFocus(); + + expect(events).toEqual([ + "mousemove", + "mouseover", + "mousemove", + "mousedown", + "blur", + "focus", + "mouseup", + "click", + "mousedown", + "mouseup", + "click" + ]); + }); }); diff --git a/src/index.js b/src/index.js index c6637987..6c602907 100644 --- a/src/index.js +++ b/src/index.js @@ -41,11 +41,12 @@ function clickBooleanElement(element) { fireEvent.click(element); } -function clickElement(element) { +function clickElement(element, previousElement) { fireEvent.mouseOver(element); fireEvent.mouseMove(element); const continueDefaultHandling = fireEvent.mouseDown(element); if (continueDefaultHandling) { + previousElement && previousElement.blur(); element.focus(); } fireEvent.mouseUp(element); @@ -55,11 +56,14 @@ function clickElement(element) { labelAncestor && clickLabel(labelAncestor); } -function dblClickElement(element) { +function dblClickElement(element, previousElement) { fireEvent.mouseOver(element); fireEvent.mouseMove(element); - fireEvent.mouseDown(element); - element.focus(); + const continueDefaultHandling = fireEvent.mouseDown(element); + if (continueDefaultHandling) { + previousElement && previousElement.blur(); + element.focus(); + } fireEvent.mouseUp(element); fireEvent.click(element); fireEvent.mouseDown(element); @@ -101,15 +105,6 @@ function fireChangeEvent(event) { event.target.removeEventListener("blur", fireChangeEvent); } -function blurFocusedElement(element, focusedElement, wasAnotherElementFocused) { - if ( - wasAnotherElementFocused && - element.ownerDocument.activeElement === element - ) { - focusedElement.blur(); - } -} - const userEvent = { click(element) { const focusedElement = element.ownerDocument.activeElement; @@ -131,10 +126,8 @@ const userEvent = { break; } default: - clickElement(element); + clickElement(element, wasAnotherElementFocused && focusedElement); } - - blurFocusedElement(element, focusedElement, wasAnotherElementFocused); }, dblClick(element) { @@ -149,14 +142,12 @@ const userEvent = { switch (element.tagName) { case "INPUT": if (element.type === "checkbox") { - dblClickCheckbox(element); + dblClickCheckbox(element, wasAnotherElementFocused && focusedElement); break; } default: - dblClickElement(element); + dblClickElement(element, wasAnotherElementFocused && focusedElement); } - - blurFocusedElement(element, focusedElement, wasAnotherElementFocused); }, selectOptions(element, values) { @@ -168,7 +159,7 @@ const userEvent = { fireEvent.mouseLeave(focusedElement); } - clickElement(element); + clickElement(element, wasAnotherElementFocused && focusedElement); const valArray = Array.isArray(values) ? values : [values]; const selectedOptions = Array.from( @@ -182,8 +173,6 @@ const userEvent = { selectOption(element, selectedOptions[0]); } } - - blurFocusedElement(element, focusedElement, wasAnotherElementFocused); }, async type(element, text, userOpts = {}) {