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

Cannot set the cursor position after programmatically modifying the value of input #971

Closed
JesseChain opened this issue Jun 12, 2022 · 6 comments · Fixed by #992
Closed
Labels
bug Something isn't working environment:react Issue specific to React released

Comments

@JesseChain
Copy link

Reproduction example

https://codesandbox.io/s/serene-lehmann-1fkp6j?file=/src/App.test.js

Prerequisites

None

Expected behavior

The position of the cursor should always be 2 if you enter anything in input

Actual behavior

The cursor position is always reset to the end

User-event version

14.2.0

Environment

Testing Library framework: @testing-library/react@11.2.5

JS framework: react@16.14.0 react-dom@16.14.0

Test environment: jest@26.0.21 @testing-library/jest-dom@5.11.9

DOM implementation: jsdom@16.4.0

Additional context

No response

@JesseChain JesseChain added bug Something isn't working needs assessment This needs to be looked at by a team member labels Jun 12, 2022
@JesseChain
Copy link
Author

I think it's caused by this code

setCleanValue(element, changes.tracked[changes.tracked.length - 1])

@ph-fritsche
Copy link
Member

Thanks for the report.

You're right. This is caused by us reapplying value changes we collected during the input event.

The underlying problem is that react@17 (don't know about earlier versions, in v18 the problem doesn't seem to exist) resets the value on controlled elements before executing the event handlers.
But it does so only in test environment.
Any programmatic change to the value property of an element automatically also sets the selection to value.length.
So while in the browser nothing happens - the selection is moved in the test.

We currently work around this by intercepting all changes to value during the input. But we don't know if a change is caused by React or by the event handler, so after the event handlers are done, we reapply the last change to value if the changes don't match this reset+update pattern.

The useLayoutEffect hook is executed after the event handlers and before our code continues, so the value change that originally happened before the hook is reapplied later.

Maybe there's a smarter workaround doing less harm.

@ph-fritsche ph-fritsche added needs specification The desired behavior is not defined yet environment:react Issue specific to React and removed needs assessment This needs to be looked at by a team member labels Jun 13, 2022
@Kreynux
Copy link

Kreynux commented Jun 15, 2022

I Have the same problem. My code is pretty much the same as shown in the codesandbox provided by dnt1996.
My test looks like this:

it("should keep cursor position when formatting input value", async () => {
    render(<personalIdNumber />)
    const user = userEvent.setup()
    const textBox = screen.getByRole("textbox")
    await user.type(textBox, "9010107777")
    expect(textBox).toHaveValue("90101077-77")
    await userEvent.type(textBox, "19", {
      initialSelectionStart: 0,
      initialSelectionEnd: 0
    })
    expect(textBox).toHaveValue("19901010-7777") // Test fails here
  })

Error console log:
Error: expect(element).toHaveValue(19901010-7777)

Expected the element to have value:
19901010-7777
Received:
19010107-7779

I use the following following environment:
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-scripts": "^5.0.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.0.1",
"@testing-library/user-event": "^14.2.0",
"@types/jest": "^27.5.1",

@github-actions
Copy link

🎉 This issue has been resolved in version 14.2.6 🎉

The release is available on:

Your semantic-release bot 📦🚀

@ph-fritsche ph-fritsche removed the needs specification The desired behavior is not defined yet label Jul 18, 2022
@ph-fritsche
Copy link
Member

@all-contributors add @dnt1996 bug

@allcontributors
Copy link
Contributor

@ph-fritsche

@dnt1996 already contributed before to bug

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

Successfully merging a pull request may close this issue.

3 participants