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

activeElement might change during userEvent.type causing runtime errors #356

Closed
beckerei opened this issue Jun 15, 2020 · 6 comments
Closed
Labels
bug Something isn't working

Comments

@beckerei
Copy link

  • @testing-library/user-event version: >= 11.1.0
  • @testing-library/dom version: 5.10.1
  • Testing Framework and version: jest@26.0.1
  • DOM Environment: jsdom jest-environment-jsdom-global@2.0.2
  • node: 13.7.0

What you did:

Using userEvent.type. We have like > 1k tests which mostly use fireEvent but slowly upgrading to userEvent. All run fine, execept for one I encountered while updating our dependencies.

As a tmp fix one can use fireEvent.change.

What happened:

I narrowed it down to start with the release of https://github.com/testing-library/user-event/releases/tag/v11.1.0

    TypeError: Cannot read property 'length' of undefined

      at calculateNewValue (node_modules/@testing-library/user-event/dist/type.js:312:43)
      at typeCharacter (node_modules/@testing-library/user-event/dist/type.js:366:43)
      at typeImpl (node_modules/@testing-library/user-event/dist/type.js:230:29)
      at node_modules/@testing-library/user-event/dist/type.js:20:14
      at node_modules/@testing-library/react/dist/pure.js:58:16

Reproduction:

Problem description:

We currently have 90 occurrences for await userEvent.type( in our codebase, yet only a single one has this issue. I don't understand (yet) what could cause this.
But I figured out the activeElement is always the body, so calling currentValue() will be undefined, as body has no value prop.

I will provide more details if I find more.

@kentcdodds
Copy link
Member

The active element not having a value property is probably going to be pretty common so we should probably improve the error message there.

If you could give us more details on what your testing we may be able to help you more.

@beckerei
Copy link
Author

beckerei commented Jun 15, 2020

I can try my best to describe the setup. I actually have not written any of the code myself, I'm just the lucky to do some maintenance task. We are actively working on a monorepo with ~40 people.

We generate a form by some json values. The underlying libs used are final-form-react and yup, but I don't think it's too important.

The test looks similar to this (I striped some names/additional expects):

it('does not submit', async () => {
  render(<Form />);

  await screen.findByText('Next');

  await userEvent.type(screen.getByTestId('form-field'), 'my value');

  await userEvent.clear(screen.getByTestId('form-field'));
  fireEvent.blur(screen.getByTestId('form-field'));

  userEvent.click(screen.getByText('Verification'));
  await screen.findByText('Connection established');
  userEvent.click(screen.getByText('Save'));

  expect(screen.getAllByText('This field is required!').length).toBeGreaterThan(
    0
  );
  expect(patch).not.toHaveBeenCalled();
});

The error appears in line await userEvent.type(screen.getByTestId('form-field'), 'my value');
Changing the line to use the following works:

fireEvent.change(screen.getByTestId('form-field'), {
  target: { value: 'my value' },
});

or

await userEvent.type(screen.getByTestId('form-field'), 'my value', {
  allAtOnce: true,
});

I removed everything besides the faulty line, still the same result. A first I was suspecting the manual call of blur to be an issue. I assume this is done to trigger the validation of the form library.

The active element not having a value property is probably going to be pretty common

true.
But when calling type you usually do this on some kind of input field (in our case it's a simple text input). I'd expect type to always access the correct element.
I've check the code and can't see how we manually change the focused element.

@beckerei
Copy link
Author

The form is conditionally rendered, but at the time we type into the field the render output is stable. So the focus is not reset to the body by this. Logging activeElement during the render phase of the component does switch between body and the input element. During the test right before and after using userEvent.type the focus is on the body.

@nickmccurdy nickmccurdy transferred this issue from testing-library/dom-testing-library Jun 16, 2020
@nickmccurdy nickmccurdy added needs investigation Someone has to do research on this question Further information is requested bug Something isn't working and removed needs investigation Someone has to do research on this question Further information is requested labels Jun 16, 2020
@tsmithATX
Copy link

I'm seeing this happen with portals where the portal component opens and has an active element but once you try to focus back to a text area to type the activeElement is the root of the portal.

@tsmithATX
Copy link

v12.0.14 addressed our issues, no longer seeing this happen!

@Junhao6503
Copy link

I am still encountering this issue due to portals. It gives me errors like:

TypeError: Cannot read property 'length' of undefined
      at setSelectionRange (node_modules/@testing-library/user-event/dist/type.js:240:70)
      at fireInputEventIfNeeded (node_modules/@testing-library/user-event/dist/type.js:269:5)
      at handleDel (node_modules/@testing-library/user-event/dist/type.js:613:5)
      at node_modules/@testing-library/user-event/dist/type.js:144:29
      at typeImpl (node_modules/@testing-library/user-event/dist/type.js:159:4)
      at type (node_modules/@testing-library/user-event/dist/type.js:73:14)
      at Object.clear (node_modules/@testing-library/user-event/dist/clear.js:26:18)
      at Object.<anonymous> (src/__tests__/UserProfile/UserProfileEdit.test.js:148:17)

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

No branches or pull requests

5 participants