NoctisHsu
9/7/2017 - 6:27 PM

unit.testing.react.with.jest.md

Unit testing react with Jest


What is a unit test?

  • When given some input, does the output look like x?
  • Runs quickly
  • Contained to a single unit of code (e.g. a function)
  • Written by developers, unlike acceptance tests

What isn't a unit test

  • Touches the database
  • Makes network requests (to APIs)
  • Touches the file system
  • It can't run at the same time as other unit tests
  • It has to run in a certain order

How are we going to test?


How should we write tests?

Discuss this

I propose BDD style:

describe('<Button />', () => {
  it('should invoke the onClick callback when clicked');
});

Behaviour driven development feels better suited to UI based testing rather than just functional definitions.


Testing a react component

This is a button component, what tests could we write?
const Button = ({ 
  onClick,
  text
}) => (
  <div onClick={onClick} className="button">
    {text}
  </div>
)

Some less useful:

// Implementation details inside tests
it('should return a <div />', () => {
  const tree = shallow(<Button text="Hello World" />);
  expect(tree.type()).toEqual('div');
});

it('should show passed text in .button', () => {
  const tree = shallow(<Button text="Hello World" />);
  const actual = tree.find('.button').text();
  expect(actual).toEqual('Hello World');
});




Some better tests:

it('should display the passed text prop', () => {
  const tree = shallow(<Button text="Hello World" />);
  expect(tree.text).toContain("Hello World");
});

it('should invoke onClick prop when clicked', () => {
  const spy = jest.fn();
  const tree = shallow(
    <Button
      text="Hello World
      onClick={spy} />
  );
  tree.simulate('click');
  expect(spy.calls).toEqual(1);
});

Shallow Rendering

  • Does not create DOM nodes
  • Returns objects describing your component tree
  • Does not render components outside the boundary of your component under test

Some enzyme gotchas

  • wrapper.simulate('click') will look for the onClick prop and invoke that
    • This means that it will invoke just the callback provided for that prop
  • Simulating events does not trigger with an Event
    • You must provide an object if you want it: wrapper.simulate('click', { id: 123 });

**This is a more complex component tree** ![](/Users/willm/Desktop/Screen%20Shot%202016-12-02%20at%2010.35.44.png)
const SeatPrefs = ({ willReserve: boolean }) => (
  <div>
    <h3>Seating Preferences</h3>
    { willReserve && <div>
      <SeatSelections />
      <SeatLocations />
      <SmallNote /> 
    </div> }
  </div>
);

Only test the immediate children

☹️

it('should render a Direction selectbox');
it('should render a Position selectbox');
it('should render a CoachType selectbox');
it('should render a Table seat checkbox');
it('should render a Power Socket checkbox');
it('should render a Luggage Rack checkbox');
it('should render a Near Toilet checkbox');

😀

it('should render <SeatSelections /> when willReserve');
it('should render <SeatLocations /> when willReserve');
it('should render <SmallNote /> when willReserve');

SeatSelections must have it's own tests

SeatLocations must have it's own tests

SmallNote must have it's own tests


Discuss