-
Notifications
You must be signed in to change notification settings - Fork 14
Front End Automated Testing
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.
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
Make sure you have all these dependencies by pulling the latest master and running yarn dev
.
Your tests should have Unit tests and Integration tests. Tests reside in the frontend/Tests folder and are generally one test file per component, however, if you are writing more complex tests that may not be the case.
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.
Here are some helpful resources for testing functional/react hook based components as well as writing tests in general.
Testing React Function Components with Hooks using Enzyme
Testing with Jest and Enzyme in React — Part 3 (Best Practices when testing with Jest and Enzyme)
How to Test React and Mobx with Jest
Testing React Components: Complete Guide
To run the front end test suite, simply run yarn test