unit-testingfocusreact-bootstrapreact-modalreact-testing

Unit Testing React Component using ReactBootstrap Modal with a Form Input element


I've react-bootstrap's Modal component which has an input and when i do the unit test for the Focus, it says it received whole document instead of just the Input element.

Does any one know why the focus went to whole doc(Does Modal make the whole document to have focused). Really appreciate the help. Below is my code

Signup.js

import { Container, Form, Modal } from 'react-bootstrap';

const Signup = () => {
const handleClick = (e) => {
  e.preventDefault();
  const element = e.currentTarget;
  const id = element.getAttribute('id');
  if (id === 'userEmail') {
    const emailLabel = document.getElementById('emailLabel');
    emailLabel.style.fontSize = '30px';
  }
};
return (
  <Container>
    <Modal show={true} autoFocus>
      <Modal.Header>Header</Modal.Header>
      <Modal.Body>
        <Form>
          <Form.Group>
            <Form.Label>
              <span id="emailLabel">Email</span>
              <Form.Control
                name="userEmail"
                id="userEmail"
                data-testid="userEmail"
                type="email"
                onClick={(e) => handleClick(e)}
              />
            </Form.Label>
          </Form.Group>
        </Form>
      </Modal.Body>
    </Modal>
  </Container>
);
};
export default Signup;

Signup.test.js

import Signup from '.';

describe('helo', () => {
it('signup', async () => {
 render(<Signup />);
 const emailInput = screen.getByTestId('userEmail');
 fireEvent.click(emailInput);
 expect(emailInput).toHaveFocus();
});
});

Result


    Expected element with focus:
      <input class="form-control" data-testid="userEmail" id="userEmail" name="userEmail" type="email" />
    Received element with focus:
      <div aria-modal="true" class="fade modal show" role="dialog" style="display: block;" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header">Header</div><div class="modal-body"><form class=""><div class="form-group"><label class="form-label"><span id="emailLabel" style="font-size: 30px;">Email</span><input class="form-control" data-testid="userEmail" id="userEmail" name="userEmail" type="email" /></label></div></form></div></div></div></div>

      123 |     const emailInput = screen.getByTestId('userEmail');
      124 |     fireEvent.click(emailInput);
    > 125 |     expect(emailInput).toHaveFocus();
          |                        ^
      126 |   });
      127 | });
      128 |

Solution

  • Consider fireEvent.click, which creates a click event and dispatches that event on the given DOM node. This works properly for most situations when you simply want to test what happens when your element is clicked, but when the user actually clicks your element, these are the events that are typically fired (in order):

    fireEvent.mouseOver(element)
    fireEvent.mouseMove(element)
    fireEvent.mouseDown(element)
    element.focus() (if that element is focusable)
    fireEvent.mouseUp(element)
    fireEvent.click(element)
    

    take a look at this post blog https://testing-library.com/docs/guide-events/