React Testing

by Andrei Fidelman

andrei.fidelman@actum.cz

fidelman

slides.com/fidelman

Maslow's hierarchy of needs

React testing

Cosmetic tests

errors do not violate the basic idea of code

Cosmetic tests

Coding style

if(true)
{
  return false
}
if (true) {
  return false;
}
import Spinner from "./Spinner"
import React, {Component} from "react"
import React, { Component } from 'react';
import Spinner from './Spinner';
let filteredArticles = articles.filter
(article => {
    console.log(article)
    return article.id != removedId
})
const filteredArticles = articles.filter
(article => article.id !== removedId);

Cosmetic tests

Coding style

ESLint

Cosmetic tests

Static typisation

let stockQuantity = 1;
...
...
...
stockQuantity = 'none';
const items = [{
    id: 1,
    value: "1"
}];

...map(item => <MyComponent key={item.id} 
               number={item.value} />);
// MyComponent.js

render() {
    const { number } = props;

    // if number => 7, sting => 16
    const value = number + 6;
    
    return <span>{value}</span>;
}

Cosmetic tests

Static typisation

// MyComponent.js

render() {
    const { number } = props;

    // if number => 7, sting => 16
    const value = number + 6;
    
    return <span>{value}</span>;
}

MyComponent.propTypes = {
    number: PropTypes.number.isRequired
};
const items = [{
    id: 1,
    value: "1"
}];

...map(item => <MyComponent key={item.id} 
               number={item.value} />);

React PropTypes

Cosmetic tests

Static typisation

// MyComponent.js
// @flow
class MyComponent extends React.Component {
  props: {
    +number: number // <- init as number
  };

  render() {
    const { number } = props;

    const value: number = number + 6; // <- init as number
    
    return <span>{value}</span>; // <- sure value is number and 7
  }
}

Flow

Unit tests

test small piece of code

Unit tests

Frameworks and Libraries

Unit tests

Jest + Reducer = ❤️

import reducer from './reducer';

describe('reducer', () => {
  test('should add article', () => {
    const stateBefore = [{
        id: 1,
        title: 'Hi',
        text: 'Wazzaaap'
    }];

    const action = {
      type: 'ADD_ARTICLE_BY_ID',
      payload: {
        id: 2,
        title: 'Hello',
        text: 'How are you'
      }
    };

    const actual = reducer(stateBefore, action);

    const expected = [{
      id: 1,
      title: 'Hi',
      text: 'Wazzaaap'
    }, {
      id: 2,
      title: 'Hello',
      text: 'How are you'
    }];


    expect(actual).toEqual(expected);
  });
});
// reducer
const defaultState = [
  {
    id: 1,
    title: 'Hi',
    text: 'Wazzaaap'
  }
];

export default (state = defaultState, action) => {
  const { type, payload } = action;

  switch (type) {
    case 'ADD_ARTICLE_BY_ID':
      return [
        ...state,
        payload
      ];
  }

  return state;
}

Unit tests

Jest + Reducer = ❤️

import reducer from './reducer';

describe('reducer', () => {
  test('should add article', () => {
    const stateBefore = () => {
      return [{
        id: 1,
        title: 'Hi',
        text: 'Wazzaaap'
      }];
    };

    const action = {
      type: 'ADD_ARTICLE_BY_ID',
      payload: {
        id: 2,
        title: 'Hello',
        text: 'How are you'
      }
    };

    const actual = reducer(stateBefore(), action);

    const expected = [{
      id: 1,
      title: 'Hi',
      text: 'Wazzaaap'
    }, {
      id: 2,
      title: 'Hello',
      text: 'How are you'
    }];


    expect(actual).toEqual(expected);
  });
});
// reducer
const defaultState = [
  {
    id: 1,
    title: 'Hi',
    text: 'Wazzaaap'
  }
];

export default (state = defaultState, action) => {
  const { type, payload } = action;

  switch (type) {
    case 'ADD_ARTICLE_BY_ID':
      return [
        // ...state, <- forget about immutability
        payload
      ];
  }

  return state;
}

Unit tests

Jest + Reducer = ❤️

Shallow and Snapshot tests

test React components

Shallow and Snapshot tests

Shallow tests

import React from 'react';
import { shallow } from 'enzyme';
// import Shallow from 'react-test-renderer/shallow';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
   it('should render the greeting', () => {
      const actual = shallow(
        <MyComponent greeting="hello world" />
      );
      const expected = <div>hello world</div>;
      expect(actual).toEqual(expected);
   });
});
import React from 'react';
export default ({ greeting }) => <div>{greeting}</div>;

Shallow and Snapshot tests

Snapshot tests

import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';

describe('MyComponent', () => {
   it('should render the greeting', () => {
      const component = shallow(
        <MyComponent greeting="hello world" />
      );
      const actual = component.toJSON();
      expect(actual).toMatchSnapshot();
   });
});
import React from 'react';
export default ({ greeting }) => <div>{greeting}</div>;
// __tests__/__snapshots__/MyComponent.react-test.js.snap
exports[`should render the greeting`] = `
<div>
  hello world
</div>
`;

e2e

from the beginning to the end

e2e

Chromedriver + Cabbie = 🤘

import assert from 'assert';
import cabbie, { startChromedriver } from 'cabbie-sync';

// Start the chromedriver server, this provides a local selenium server
// You must install chromedriver to use this.
startChromedriver();

// connect to chromedriver, adding {debug: true} makes cabbie log each method call.
const driver = cabbie('chromedriver', {debug: true});

try {
  // navigate to a url in the currently active window
  driver.activeWindow.navigateTo('http://example.com');

  // get an element, and check that its text equals some expected value
  assert.equal(
    driver.activeWindow.getElement('h1').getText(),
    'Example Domain',
  );
} finally {
  // whether tests pass or fail, dispose of the driver
  driver.dispose();
}

Resources

“Tests are stories we tell the next generation of programmers on a project.”

– Roy Osherove

React Testing

by Andrei Fidelman

andrei.fidelman@actum.cz

fidelman

slides.com/fidelman

Q&A

React testing

By Andrei Fidelman

React testing

For the devTalks.js in Actum

  • 304