React and component testing

More and more people are doing React apps without caring problem situations. Here's a compact article on testing them

Selling speach

Why React component testing is needed. Why it cannot be thought just as an UI.

  • Components have logic inside and mostly aren't dummy (pure) components.
  • Component's state change on user actions and combination of container components.
  • When there is a long nesting of components, testing data flow prevents building new components on problems.
  • React component testing is easy.
  • With TDD development drives clear code structure.
  • It makes testing frontend more like backend logic testing and more proofable.

What to test

To focus on valuable testing, here is a checklist.

Rendering Make a simple test for every component for just to make sure it renders. This is test is also called as a sanity-check or smoke test.

Output can change Output needs to be expected event though something somewhere in other end of component chain changes. Check edge cases: what if list has no items and if it has 25 items?

Passed data affects on state If state changed depending on given properties. Check edge cases. What if there is no expected property?

Components have events Element events need to trigger and have wanted result. There is a change to test if method is called and is that method really binded. Before overdoing, define which one is the real goal: affect of feature or detailed testing.

Testing tools

Here is some testing tools usually used with React testing. These are also tools used in code examples.

  • Enzyme
    Renders components for test cases and allows to use their events for testing state and DOM changes.
  • Jest
    Test platform including assertion and monitoring tools all in single zero-configurate-needed package.

Test code snippets

Code snippets done with Jest and Enzyme. This part will live when I create more tests.

Render test / smoke test / sanity-check

it('renders', () => {
  const wrapper = shallow(<Cake />);

Check component content as string

it('outputs correct', () => {
  const wrapper = shallow(<Cake />);
  expect(wrapper.text()).toBe('Happy birthday!');

Component has a certain class

it('has right class', () => {
  const wrapper = mount(<Cake />);

Component has a certain class after action

it('adds a modifier class after action', () => {
  const wrapper = mount(<Cake />);