How to configure Webpack with React Testing Library from the ground up

macmacky

Mark Abeto

Posted on May 17, 2020

How to configure Webpack with React Testing Library from the ground up

Hi Guys Good Day!

React testing Library is an alternative library for testing our components in
React. It is more lightweight compared to Airbnb's Enzyme and it is much easier to learn.

Yeah, I know you can directly use this library in create-react-app write away after installing two modules but I wanna show you how to configure this using webpack and friends from the ground up. So Let's go.

Do this in the command line on your desktop.

  mkdir webpack-react-testing && cd webpack-react-testing
Enter fullscreen mode Exit fullscreen mode

What we do here is we are making a folder webpack-react-testing and
changing our current directory to webpack-react-testing in the command line.

and write this again in the command line.

npm init --y
Enter fullscreen mode Exit fullscreen mode

What we do here is making a package.json with the default values.

and we are gonna install the development modules that we need in the project.

npm i -D webpack webpack-cli webpack-dev-server @babel/cli 
@babel/core @babel/preset-env @babel/preset-react babel-jest 
babel-loader jest html-webpack-plugin @testing-library/react @testing-library/jest-dom
Enter fullscreen mode Exit fullscreen mode

If you wanna know what these modules do you can read it in one of my previous post link. But the important part is we installed
the @testing-library/react testing library and also this library depends
on the @testing-library/jest-dom so we installed it too.

and lastly these modules.

 npm i -P react react-dom
Enter fullscreen mode Exit fullscreen mode

Our webpack.config.js file.

const HTMLWebpackPlugin = require('html-webpack-plugin');
const { join } = require('path');
const { HotModuleReplacementPlugin } = require('webpack');

const mode = process.env.ENV || 'development';

module.exports = {
  mode,
  entry: join(__dirname, 'index.js'),
  output: {
    path: join(__dirname, 'build'),
    filename: 'index.bundled.js'
  },
  devServer: {
    port: 1000,
    hot: true,
    open: true,
    historyApiFallback: true
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env', '@babel/preset-react']
        }
      }
    ]
  },
  plugins: [
    new HotModuleReplacementPlugin(),
    new HTMLWebpackPlugin({
      favicon: false,
      showErrors: true,
      cache: true,
      template: join(__dirname, 'index.html')
    })
  ]
}
Enter fullscreen mode Exit fullscreen mode

If you wanna know what this configuration does you can read it in one of my previous post link.

Our babel.config.js file.

module.exports = {
  presets: ['@babel/preset-env', '@babel/preset-react'],
};
Enter fullscreen mode Exit fullscreen mode

In the babel config file we specify the presets we are gonna use in this project.

Our jest.config.js file.

module.exports = {
  setupFilesAfterEnv: ['<rootDir>/setUpTests.js'],
};
Enter fullscreen mode Exit fullscreen mode

In the jest config file we specify what is the path or paths of the configuration files we are gonna use before executing any tests.

Our setUpTests.js file.

import '@testing-library/jest-dom/extend-expect';
Enter fullscreen mode Exit fullscreen mode

In the setup file, we just import this module.

make a new folder named components.

  mkdir components
Enter fullscreen mode Exit fullscreen mode

In this folder, we have two components App.js and Input.js.

Our App.js file.

import React from 'react';

const App = () => {
  return (
    <>
      <h1>Hello World</h1>
    </>
  )
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Our Input.js file.

import React, { useState } from 'react';

const Input = ({ id = '', label = '', type = 'text' }) => {
  const [value, handleChange] = useState('');
  return (
    <div>
      <label htmlFor={id}>{label}</label>
      <input type={type} id={id}
        data-testid={id}
        label={label}
        onChange={({ target }) => {
          handleChange(target.value)
        }}
        value={value}
      />
    </div>
  )
}

export default Input;
Enter fullscreen mode Exit fullscreen mode

Our index.js file in our root folder.

import React from 'react';
import { render } from 'react-dom';
import App from './components/app';

render(<App />, document.getElementById('root'))
Enter fullscreen mode Exit fullscreen mode

And lastly, in our tests folder, we have our index.test.js file.

import React from 'react';
import { screen, render, cleanup, fireEvent } from '@testing-library/react'
import Input from '../components/Input';
import App from '../components/App'

describe('App component', () => {
  beforeAll(() => {
    render(<App />)
  })

  it('should have the right message in the dom', () => {
    const message = 'Hello World';

    expect(screen.getByText(message)).toBeInTheDocument()
  })

  afterAll(cleanup)
})

describe('Input component', () => {
  let input, inputID;

  beforeAll(() => {
    const { getByTestId, getByLabelText } = render(<Input label='username' id='username' />)
    input = getByLabelText('username')
    inputID = getByTestId('username');
  })

  it('should have the default value', () => {
    expect(input.value).toBe('')
    fireEvent.change(input, { target: { value: 'ok' } })
  })

  it('should have the updated value', () => {
    expect(input.value).toBe('ok')
  })

  it('should have an element with this id', () => {
    expect(inputID).not.toBeNull();
  })

  afterAll(cleanup)
})
Enter fullscreen mode Exit fullscreen mode

Then run this command jest. I hope all the test passes on your computer.
Some of the modules that we installed were not used especially the html-webpack-plugin. If you want you can use this as a development server too just add a new script in the package.json - "start": "webpack-dev-server" and also make an index.html that looks like this in the root folder.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>React App</title>
</head>
<body>
  <div id="root">

  </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Happy Testing.

Thanks guys for reading this post.

Have a Nice Day and Stay Safe 😃!.

💖 💪 🙅 🚩
macmacky
Mark Abeto

Posted on May 17, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related