JS - Using Jest with Import and Export statements
Purpose
When using new tools I like to create my own documentation of setup.
In this case we will be looking at: Jest
Jest is a simple testing framework for javascript that uses very similar syntax to RSpec. In fact, it even supports the *.spec.js file extension. I however, like to use the *.test.js file, but you are free to do as you please.
Quick Start
At the time of writing this, I am using Jest 24.9, Babel 7.6, and ESLint 6.5
ESLint is not necessary for this Jest to properly use the import / export syntax, however, I like it for using prettier within my work environment.
EDIT
I realized I never included the use of Webpack for bundling everything! I added the command below and my webpack config
# If its a new project
npm init
# install eslint, jest, and babel packages
npm install --save-dev webpack webpack-cli webpack-dev-server jest babel-jest babel-loader @babel/core @babel/preset-env regenerator-runtime eslint eslint-plugin-jest
# create a config file for jest and eslint
npx jest --init
npx eslint --init
Then modify eslint and jest config files accordingly.
My webpack config
My Jest Config npx jest --init
I simply used the default from npx eslint --init
and chose the appropriate options for the project.
I added the following lines for use with Jest.
module.exports = {
// ...
env: {
"jest/globals": true,
},
extends: ["plugins:jest/recommended", "eslint:recommended"],
plugins: ["jest"],
// ...
}
My Babel Config npx babel --init
so you must generate your own config file.
I generated my using the Docs
// babel.config.js
module.exports = {
presets: [
[
"@babel/preset-env",
{
targets: {
node: "current",
},
},
],
],
}
Now, all your tests will go into a __tests__/
directory and you can name them
*.test.js
and you’re ready to rock and roll.
The longer, more in depth guide
As with all projects using javascript, start with creating your package.json.
npm init
After filling in the appropriate fields, you will have a package.json and package-lock.json ready to go. Alternatively you can use yarn, and I actually prefer yarn for many reasons that I will not get into in this guide.
Installing Jest
Jest’s documentation is quite good. And I quite enjoyed reading it, I recommend you check it out
To start run the following:
npm install --save-dev jest
That’s it! You’re done! Technically this is all you need to run Jest. However, if you’re using a non-Node based project IE: browser based project using ES6 imports, Jest will quickly get in the way.
Also, as a quick note, if you go into your jest config, the file it searches for tests
is the __tests__
directory. The getting started pages doesn’t mention this, but
if you’re like me, you like to use a seperate tests directory.
Installing Babel
Jest uses the Node syntax of module.exports = <variable>
and require('<file>')
,
it will not support the import
and export
statements of ES6.
Luckily, people way smarter than me already thought of this, so there is a babel transpiler for this.
To use this transpiler, you can install the following for use with Jest.
npm install --save-dev babel-jest @babel/core @babel/preset-env regenerator-runtime
babel-jest
, @babel/core
, @babel/preset-env
are technically the only required
packages. regenerator-runtime
according to the documentation is not needed with
NPM versions > 3/4 or Yarn. However, I included it just in case someone is using
a different package manager.
Adding a babel config
The next step is to add a Babel config.
My Babel Config npx babel --init
so you must generate your own config file.
I generated my using the Docs
// babel.config.js
module.exports = {
presets: [
[
"@babel/preset-env",
{
targets: {
node: "current",
},
},
],
],
}
After adding this to the root of your project, you should be ready to start using import / export statements wherever you want!
Ok, so how does this all work?
Well, based on what I have read it’s super simple. Let’s take what the documentation uses. Given the following file:
// src/sum.js
export default function sum(a, b) {
return a + b
}
// __tests__/sum.test.js
import sum from "../src/sum.js"
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(3)
})
So why does this work?
Well, Babel essentially takes your import statement:
import sum from "../src/sum.js";
And turns it into
const sum = require('../src/sum.js');
And takes your export statement:
export default function sum(a, b) {
and turns it into
function sum(a, b) {
...code omitted for brevity
}
module.exports = sum
There are key differences when looking at import / export vs module.exports / require if you dig further and look at the specs. I won’t get into the differences here, but there is a reason import / export statements are currently only experimental in NodeJS.
Technically, you could stop here, but I like to use ESLint to both lint and enforce code style. If you don’t tell ESLint about Jest, it will throw up many warnings. So, lets fix that.
Installing ESLint
npm install --save-dev eslint eslint-plugin-jest
npx eslint --init
This will generate a eslint config file for you once you choose from the command line options.
I added the following lines for use with Jest in my .eslintrc.js
file.
module.exports = {
// ...
env: {
"jest/globals": true,
},
extends: ["plugins:jest/recommended", "eslint:recommended"],
plugins: ["jest"],
// ...
}
Closing thoughts
Setting up Jest for the first time took a bit of work, but I got it all working to
my liking and used it for testing in my TicTacToe project