React.js

Types of testing

  • static checks - via TypeScript, linters, jsdoc, etc
  • unit tests - ensure smallest parts of application work as intended
  • integration tests - widgets, forms, etc work correctly
  • e2e tests - check app as if a user, from auth till checkout

Static checks

  • always use linters
  • try to benefit from typings even if you don't use TypeScript

Static checks

in VSCode:

// jsconfig.json
{
  "compilerOptions": {
    "checkJs": true
  },
  "exclude": ["node_modules", "**/node_modules/*"]
}

Static checks

const sum = (a,b) => a + b;

const total = sum(3)

Static checks

/**
 * 
 * @param {number} a 
 * @param {number} b 
 * @returns {number} sum
 */
const sum = (a,b) => a + b;

const total = sum(3)

Static checks

Unit tests

UNIT TESTING is a type of software testing where individual units or components of a software are tested.

Unit tests

Unit tests

Unit tests are NOT meant to ensure application works as expected and catch all the bugs

Unit tests

  • acts as a documentation
  • helps you to design better
  • gives confidence to change code at a later date

Unit tests

const buildURL = ({ version, domain, isPublic, config }) => {
  const { API_GATEWAY, API_GATEWAY_PUBLIC, PROXY_URL, MAILER_URL } = config;

  if (version === 'v3') {
    const gateway = isPublic ? API_GATEWAY_PUBLIC : API_GATEWAY;

    if (domain[0] === '/') {
      return `${gateway}${domain}`;
    }

    return `${gateway}/${domain}`;
  }

  if (version === 'proxy') {
    return PROXY_URL;
  }

  return MAILER_URL;
};

Unit tests

const { api } = Resource.create(''); // ?
const { api } = Resource.create({ domain: '' }); // ?
const { api } = Resource.create('/'); // ?
const { api } = Resource.create({ domain: '/' }); // ?
const { api } = Resource.create('statements'); // ?
const { api } = Resource.create('/statements'); // ?
const { api } = Resource.create({ domain: '/statements' }); // ?

Unit tests

test('should point to api with trailing slash if leading slash passed', () => {
    const { api } = Resource.create('/');
    const expected = 'https://app-staging.comp.com/api/';
    expect(api.defaults.baseURL).toEqual(expected);
});
test('should point to api when domain with slashed provided', () => {
    const { api } = Resource.create({ domain: '/' });
    const expected = 'https://app-staging.comp.com/api/';
    expect(api.defaults.baseURL).toEqual(expected);
});
test('should point to api with trailing slash if empty string provided', () => {
    const { api } = Resource.create('');
    const expected = 'https://app-staging.comp.com/api/';
    expect(api.defaults.baseURL).toEqual(expected);
});
test('should point to mailer when empty domain provided', () => {
    const { api } = Resource.create({ domain: '' });
    const expected = 'https://app-staging.comp.com/api/v2';
    expect(api.defaults.baseURL).toEqual(expected);
});

Unit tests

  • You will have more code in unit test than in function itself
  • Do not do any logic inside of your tests, be as simple and straightforward as possible
    • otherwise, who will test the test?
  • Embrace TDD, especially for complex bits of applications

Test Driven Development

Jest

Jest is a delightful JavaScript Testing Framework with a focus on simplicity.

⚠️ In practice: not so simple at all, especially when you need to mock modules

Enzyme

Enzyme is a JavaScript Testing utility for React that makes it easier to test your React Components' output. You can also manipulate, traverse, and in some ways simulate runtime given the output.

Component Unit tests

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

test('CheckboxWithLabel changes the text after click', () => {
  // Render a checkbox with label in the document
  const checkbox = shallow(<CheckboxWithLabel labelOn="On" labelOff="Off" />);

  expect(checkbox.text()).toEqual('Off');

  checkbox.find('input').simulate('change');

  expect(checkbox.text()).toEqual('On');
});

⚠️ In practice: "shallow" is not good enough

Resources