Skip to content

Front End Automated Testing

James Keary edited this page Sep 23, 2019 · 6 revisions

Whenever you write a component, it needs to come with a bunch of tests. Tests should be written in the front end's /test directory. Please test all your components before creating a PR.

Test Writing Techs

We are using Jest, Enzyme and React Testing Library.

Jest -> https://jestjs.io/en/ Enzyme -> https://airbnb.io/enzyme/docs/api/ React Testing library -> https://github.com/testing-library/react-testing-library

On Writing Test Cases

Your tests should have Unit tests and Integration tests.

What to test for unit tests? We want to test ui pieces and component props. Jest and Enzyme are good for that. Heres an example of a unit test:

import { shallow, configure } from "enzyme"
import LoginForm from "../src/components/LoginForm"
import Button from "@material-ui/core/Button"
import Adapter from "enzyme-adapter-react-16"
import { render, fireEvent, cleanup } from "@testing-library/react"

describe("<LoginForm />", () => {
  let wrapper
  let usernameInput
  let signInButton

  // Create initial props that get passed into the component
  const initialProps = {
    location: {
      state: {
        from: {
          pathname: "/",
        },
      },
    },
  }

  // Unit testing block
  describe("Unit tests", () => {
    // what to do before each test
    beforeEach(() => {
      // Render the login form component, pass in props. (Shallow method renders the component without its children, good for unit tests.)
      wrapper = shallow(<LoginForm {...initialProps} />)
      usernameInput = wrapper.find("#username")
      signInButton = wrapper.find(Button)
    })

    // what to do after each test
    afterEach(() => {
      jest.clearAllMocks() // if there are mocks created
    })

    // Here's the actual test
    it("should have a username inputs", () => {
      expect(usernameInput.length).toEqual(1)
    })

    // Heres another testing props on a Material-UI button
    it("should have the expected props on the button", () => {
      expect(signInButton.props()).toEqual({
        type: "button",
        variant: "contained",
        style: expect.objectContaining({
          marginTop: "10px",
        }),
        onClick: expect.any(Function),
        children: "Sign In",
      })
    })
  })
})

On integrations tests we are testing changes. In order to write a good integrations test you need to think about changes. What are the crucial things that change depending on some external influence? What can I easily break in this component? What would break the application's expected behavior? Those are what you should write tests on. For integrations tests that's where the React Testing Library comes in handy. You can write integrations tests without it using just Jest and Enzyme, but React Testing Library has ways to test React Hooks, which we use. Heres an example of an integrations test

import React from "react"
import { shallow, configure } from "enzyme"
import LoginForm from "../src/components/LoginForm"
import Button from "@material-ui/core/Button"
import Adapter from "enzyme-adapter-react-16"
import { render, fireEvent, cleanup } from "@testing-library/react"

configure({ adapter: new Adapter() })

describe("<LoginForm />", () => {
  let wrapper
  let usernameInput
  let passwordInput
  let signInButton

  // Create initial props that get passed into the component
  const initialProps = {
    location: {
      state: {
        from: {
          pathname: "/",
        },
      },
    },
  }
  // Integrations Testing
  describe("Integrations tests", () => {
    beforeEach(() => {
      // Render the login form component, pass in props. (render method renders the component with its children, good for integrations tests, uses react-test-library.)
      const { getByLabelText, getByText } = render(
        <LoginForm {...initialProps} />
      )
      usernameInput = getByLabelText(/Username/i)
      passwordInput = getByLabelText(/Password/i)
      signInButton = getByText("Sign In")
    })

    afterEach(cleanup)

    it("Username text change in onChange event", () => {
      expect(usernameInput.value).toBe("")

      fireEvent.change(usernameInput, { target: { value: "James" } })

      expect(usernameInput.value).toBe("James")
    })
  })
})

This has some react-test-library stuff in it so definitely look into those docs.

Resources

Here are some helpful resources for testing functional/react hook based components as well as writing tests in general.

https://medium.com/@acesmndr/testing-react-functional-components-with-hooks-using-enzyme-f732124d320a https://blog.usejournal.com/testing-with-jest-and-enzyme-in-react-part-3-best-practices-when-testing-with-jest-and-enzyme-ae3fe0c39d06 https://semaphoreci.com/community/tutorials/how-to-test-react-and-mobx-with-jest https://www.freecodecamp.org/news/testing-react-hooks/

Clone this wiki locally