How to configure Webpack with React Testing Library from the ground up
Tags: testing, react, tutorial, webdev
Published: 2020-05-17 06:33:30

##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.
```cmd
  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.
```cmd
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.

```cmd
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](https://dev.to/macmacky/how-to-configure-react-with-webpack-friends-from-the-ground-up-2c5g). 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.
```cmd
 npm i -P react react-dom
```

Our __webpack.config.js__ file.

```js
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](https://dev.to/macmacky/how-to-configure-react-with-webpack-friends-from-the-ground-up-2c5g).

Our __babel.config.js__ file.
```js
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.
```js
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.
```js
import '@testing-library/jest-dom/extend-expect';
```
In the __setup__ file, we just import this module.

make a new folder named __components__.

```cmd
  mkdir components
```

In this folder, we have two components __App.js__ and __Input.js__.

Our __App.js__ file.
```js
import React from 'react';

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

export default App;
```

Our __Input.js__ file.
```js
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.
```js
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.
```js
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.
```html
<!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 :smiley:!.