Testing React Components

Tools, Purpose & Patterns

Rajat Vijay

Frontend Engineering Manager

Certa - No Code workflow management and automation (SAAS)

TS

ReactJS

@rajatvijay

@rajatvijay

test-driven development

Tools & Purpose

  1. Jest
  2. jest-dom
  3. react-testing-library
  4. user-event
  5. jest-axe

Agenda

  1. What is Jest?
  2. What is jest-dom?
  3. Why react testing library?
  4. User event module
  5. Testing Prop updates
  6. Test accessibility & jest-axe
  7. Abstracting render function
  8. Integrations test cases

Jest

Jest is a Javascript test runner

  1. A single command to run all the tests
  2. Watch mode
  3. Assertions utilities - expect
  4. Coverage reporting facility
  5. Running tests in isolation - test.only
  6. Creating specifications - test.todo

jest-dom

Extending jest asserts to add more DOM specific assertions

test("renders learn react link", () => {
  const root = document.createElement("div");
  render(<App />, root);
  const button = root.querySelector("button")!;
  expect(button.disabled).toBe(true);
});

Test if a button is disabled

import "@testing-library/jest-dom";

test("renders learn react link", () => {
  const root = document.createElement("div");
  render(<App />, root);
  const button = root.querySelector("button")!;
  expect(button).toBeDisabled();
});

Test if a button is disabled

jest-dom

react-testing-library

Essentially just a set of functions to query the DOM

  1. Test how a user will interact with the component
  2. Never tests a component state or instance variables
  3. Tests depend on the rendered DOM, not the react component tree
  4. Migrate from classes to functions => Tests still work
  5. Migrate from HOC to hooks => Tests still work

react-testing-library

  1. Render DOM from a react component

  2. Query that DOM

  3. Use jest assertions to test expected output

  4. Better debugging capabilities
  5. Better event management: fireEvent

user-event

fireEvent.change v/s user.type

  1. focus event
  2. keydown event
  3. keyup event
  4. blur event

Testing prop updates

test("should call the onSubmit2 after re redering", () => {
  const onSubmit1 = jest.fn();
  const { rerender } = render(<App onSubmit={onSubmit1} />);
  const input = screen.getByLabelText("Name");

  user.type(input, "Rajat");

  const onSubmit2 = jest.fn();
  rerender(<App onSubmit={onSubmit2} />);

  const button = screen.getByRole("button");

  user.click(button);

  expect(onSubmit1).toBeCalledTimes(0);
  expect(onSubmit2).toBeCalledTimes(1);
});

Testing accessibility

It's virtually impossible to test accessibility issues in the component.

But jest-axe can help you cover most obvious cases

Custom render function

const renderWithRedux = (
  ui,
  {
    initialState,
    store = createStore(
      rootReducer,
      initialState,
      applyMiddleware(thunkMiddlware)
    ),
  } = {}
) => {
  return render(<Provider store={store}>{ui}</Provider>)
};

Integration tests

  1. Testing a parent component that renders a bunch of child components
  2. Test a core user flow: Signup, Login, order placing, payment, etc
  3. Write more integration tests as compared to unit tests
  4. NOTE: Never make a network call

@rajatvijay

@rajatvijay

Made with Slides.com