loading...
Cover image for How to configure Webpack with React Testing Library from the ground up

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

macmacky profile image Mark A ・4 min read

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

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

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

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

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')
    })
  ]
}

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'],
};

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'],
};

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';

In the setup file, we just import this module.

make a new folder named components.

  mkdir components

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;

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;

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'))

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)
})

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>

Happy Testing.

Thanks guys for reading this post.

Have a Nice Day and Stay Safe 😃!.

Posted on by:

macmacky profile

Mark A

@macmacky

a Full-Stack developer who likes reading Tom Clancy's books and loves talking with dogs.

Discussion

pic
Editor guide