Beginning development with ReactJS & TypeScript (Part-2)

This post’s focus is on testing the components for Tic-Tac-Toe game created in Part-1

Setup

  • Checkout the tag  step-4
  • Pull the new dependencies for this step by simply running yarn at the root of the project

Dependencies needed for Testing

  • Jest, a JS testing framework from Facebook but widely used for testing React applications
  • Enzyme from Airbnb which makes it easier to traverse through React Component and helps interact with the components (Issue events like clicking on a button, finding an element for asserting it’s value, etc)

Update the package.json with these additional dev dependencies and their corresponding type definition packages.

"devDependencies": {
"enzyme": "^3.2.0",
"enzyme-adapter-react-16": "^1.1.0",
"react-test-renderer": "",
"@types/enzyme": "^3.1.4",
"@types/jest": "^21.1.2",
"@types/react-test-renderer": "",
"@types/enzyme-adapter-react-16": ""
}

Export the components so that they can be imported in to the tests (MDN’s primer on ES6 exports)

Add the export statements for the Game, Board and Square components. ‘App’ component is the default export of App.tsx (The class declaration starts with ‘export default’)


export { Game }
export { Board }
export { Square }

Let’s start with Testing the components! Here is the final App.test.tsx with the tests beings reviewed below.

VsCode Setup for debugging Jest tests with TypeScript using React

Open up the launch.json and add the following debug config (Credits)


"configurations": [
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/react-scripts-ts",
"runtimeArgs": [
"--inspect-brk",
"test"
],
"args": [
"--runInBand",
"--no-cache",
"--env=jsdom"
],
"cwd": "${workspaceRoot}",
"protocol": "inspector",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}

Now you can put the break points as needed and hit F5 to begin a debug session.

Import the necessary dependencies


import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as enzyme from 'enzyme';
import * as ReactTestRenderer from 'react-test-renderer';
import * as Adapter from 'enzyme-adapter-react-16';
import App from './App'
import { Board, Game, Square } from './App';

Configure Enzyme once before running the tests


beforeAll(() => {
    enzyme.configure({ adapter: new Adapter() })
})

The test for the App component in App.test.tsx is pretty basic and uninteresting. It just verifies if the entire app loads without any issues. The Game component is subjected to a Snapshot test which is also pretty straight forward.

Here’s a basic test for the Board component to check that it loads 9 squares, no more and no less. We use enzyme’s shallow method to render the Board Component and find the number of the instances of the ‘Square’ components that it loads.


describe('', () => {
    it('should render three  components', () => {
        const wrapper = enzyme.shallow()
        expect(wrapper.find('Square').length).toEqual(9)
    })
})

Let’s look a test for the Square component. The component accepts two inputs

  • An anonymous function that should be invoked during a click event
  • The value to be displayed after the button is clicked.

So we begin by creating a mock function by invoking jest.fn() and create a constant squareValue.  We pass these to the Square component while rendering it with Enzyme. A button click is now issued through Enzyme. We can now verify if the mock function is called once and if the square displays the value ‘X’.


describe('', () => {
    it('when clicked it should invoke the function attached to the click event', () => {  //Create the necessary input values for the test case const squareValue = 'X' const mockOnClick = jest.fn()  const wrapper = enzyme.shallow()  wrapper.find('button').simulate('click') expect(wrapper.find('button').props().children).toEqual('X') expect(mockOnClick.mock.calls.length).toBe(1) 
     })
})

I’ve done extensive development in Angular 2 using initial releases of VSCode in early 2016. It looked very promising but I had to switch to Intellij/WebStorm as VSCode lacked refactoring capabilities such as extracting methods from a set of lines, refactoring variable names with ease and some other features. But it has come a long way since then.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.