Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect event.target.selectionStart value when using left arrow and backspace keys #515

Closed
oliwerin opened this issue Dec 3, 2020 · 2 comments · Fixed by #622
Closed
Labels
bug Something isn't working released

Comments

@oliwerin
Copy link

oliwerin commented Dec 3, 2020

  • @testing-library/user-event version: 12.4.0
  • Testing Framework and version: Jest (using react-scripts, version: 3.4.3)
  • DOM Environment: @testing-library/jest-dom (5.11.6)

Relevant code or config
I'm using useState here just to be able to display the event.target.selectionStart value and demonstate the issue.

// component
export default function App() {
  const [selectionStart, setSelectionStart] = useState(0);

  const onChangeHandler = (event) => {
    setSelectionStart(event.target.selectionStart);
  };

  return (
    <div className="App">
      <input onChange={onChangeHandler} data-testid="input" />
      <code>
        event.target.selectionStart:{" "}
        <span data-testid="selectionStartValue">{selectionStart}</span>
      </code>
    </div>
  );
}
// test
userEvent.type(input, "123{arrowleft}{arrowleft}{backspace}");

const selectionStartValue = screen.getByTestId("selectionStartValue");
expect(selectionStartValue).toHaveTextContent("0"); // it fails - the value is 2 instead

What you did:
I discovered it when writing a Jest test for a React component which is an input reacting to onChange and relying heavily on the event.target.selectionStart value passed in this event. I used userEvent.type in the test.

What happened:
I noticed that when the cursor is not at the end of the text in the input and backspace is pressed, the value of event.target.selectionStart provided by userEvent.type is different from the value I get in my browser.

In order to see a more tangible example, please see the CodeSandbox project I created and linked below and follow these steps:

  1. Type "abc" in the input
  2. Hit left arrow button on your keyboard twice
  3. Hit backspace
  4. Check the value of event.target.selectionStart

Result in the browser: 0
Result in the test (App.test.js): 2

Reproduction repository:
https://codesandbox.io/s/user-event-and-backspace-selectionstart-nx6ij?file=/src/App.test.js

Problem description:
I think the problem is related to fireInputEventIfNeeded. The value of event.target.selectionStart in fireEvent is incorrect (at least in my case) but it's correct in the setSelectionRange called at the end of the function (line 319). Shouldn't it be called before the event is fired?

user-event/src/type.js

Lines 295 to 324 in e9dd0a6

function fireInputEventIfNeeded({
currentElement,
newValue,
newSelectionStart,
eventOverrides,
}) {
const prevValue = getValue(currentElement())
if (
!currentElement().readOnly &&
!isClickable(currentElement()) &&
newValue !== prevValue
) {
if (isContentEditable(currentElement())) {
fireEvent.input(currentElement(), {
target: {textContent: newValue},
...eventOverrides,
})
} else {
fireEvent.input(currentElement(), {
target: {value: newValue},
...eventOverrides,
})
}
setSelectionRange({
currentElement,
newValue,
newSelectionStart,
})
}

Suggested solution:
As in the problem description. I'm happy to make a pull request if you confirm my reasoning is correct.

@ph-fritsche
Copy link
Member

The problem seems to be with the implementation of HTMLInputElement.setSelectionRange in jsdom.

See #501 (comment)

@ph-fritsche ph-fritsche added bug Something isn't working and removed accuracy Improves the accuracy of how behavior is simulated labels Mar 16, 2021
ph-fritsche added a commit that referenced this issue Mar 24, 2021
ph-fritsche added a commit that referenced this issue Mar 24, 2021
* fix: apply selection on input event

* fix: use selection helper for arrows

* fix: apply changes before input event

* test: update tests

* test: reproduce #515
@github-actions
Copy link

🎉 This issue has been resolved in version 13.0.13 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants