I'm back in the burger project and here, I now want to add some testing. For that
we should first make sure that npm start is not running because we need to install some additional packages
after all we're not just using jest but also enzyme.
Now if we have a look at our package.json file and we scroll a little bit up, we see that jest
is indeed installed, you might have a different version but it should be installed
but enzyme isn't.
So let's first of all install that with npm install --save enzyme,
now that alone won't do the trick though,
we need to install two additional packages to make it work correctly with jest and react.
The first is that we need to install the react test renderer package,
that is a dependency of enzyme which we need to install separately and we need to install an adapter
of the enzyme package to our current react
version. So here this is the enzyme adapter-react-16 version 4 react 16.
All these are now added to the package.json
and of course installed in the node modules folder and once this did finish, we are ready to move on and write
our first test.
So here it did finish,
now let's write our first test and I want to start with writing a test for a component because obviously in
react,
we talk constantly about components
so why don't we start with testing one.
Now let me start with a functional component here because that's of course a super easy way of testing
and then we'll also move to containers and thereafter, to redux.
Now I want to start with my navigation items component here, in the navigation folder in the components
folder, that's the navigation items component,
now keep in mind most of your react components are just functions and therefore they only depend on
the props they receive,
that's something you have to keep in mind for testing.
Now let's create a testing file for this component,
therefore next to it in the same folder, I'll add a new file which I'll name NavigationItems.test.js
the .test.js is important because that is automatically picked up by create react
app once
we run a special command and will then be included in the testing and therefore will be tested.
Now inside this test file, I now can start writing my test and a test uses just by default and just on
the other hand gives us a couple of methods to define the test.
The first important method is the describe method,
you don't need to import it in that file,
it will automatically be made available in our create react app project
once we run the test command. Describe is a function that takes two arguments, the first is just a description
of the test bundle
this file holds
so here I'll simply name this NavigationItems and I'm writing it like a jsx element but that's not required.
This is only what you'll see later in the console output
so it should be something which allows you to identify which kind of tests we'll run here.
The more interesting part comes in a second argument, that is your testing function.
It's a normal javascript function and I'll use an ES6 arrow function here, in here you're going to
describe, you're going to write your actual tests. Now to do that,
you write a test by writing it,
that's another function which will just be available.
It describes or allows you to write one individual test,
it also takes two arguments.
The first one is again just a string, a description which will appear in the console
and typically you just complete the sentence so it and then you describe what it should do.
So it should
and now let's look into our NavigationItems component,
let's say by default if we're unauthenticated, this component should render one navigation item,
the second one should not be rendered and that here it should render one more leading to /auth,
so it should render to navigation items
if we are not authenticated.
So that is what we want to test so let's write the sentence,
it should render to navigation item elements if not authenticated.
So this is just my description and it doesn't matter what you write here,
this is not parsed or anything like that, it should just be something meaningful you recognize in a
console because if the test fails, you want to know which test failed.
So that's the first argument to the it function,
the second argument is now again a testing function describing the actual test, here that is just a normal
javascript function
I'm again going to use an arrow function and in here, we write our actual testing logic.
Now what we want to do is we want to create an instance of this component as it would be rendered to
the dom, to the real dom through react and then have a look into the rendered component and see what
was rendered for the case that the isAuthenticated prop is false.
Now you might think that for this, we obviously need to render the entire react application because
navigation items is just one tiny piece in the entire react application, that is where an enzyme comes
in, this testing package. Enzyme allows us to just render this navigation items component standalone independent
of the entire other react application,
that's the whole idea behind the enzyme package, that we can really write unit tests, isolated tests, tests
where we don't need to render the complete react app.
So let's import enzyme then, I need to import something from enzyme, now I'll come back
to that something
but first I'll also need to configure enzyme and connect it to my react version. For that,
I need to import the adapter and it's a default export so you you may name this whatever you want.
The adapter from enzyme adapter react 16, this package and from the enzyme package, we now only need to
import something specific,
this is a named export
so we need curly braces, the configure function. With these two imports added
here above the described function, we can now execute configure and pass a javascript object to configure.
There we should set up an adapter property and assign new adapter as a constructor function,
so this adapter is instantiated with new adapter and that's all, with that enzyme is connected.
Now we want to render a navigation items component and then look into it, for this enzyme gives us a
specific helper method we can use,
we import that too,
it's the shallow function. Shallow is the most popular or the best way of rendering react components
in many circumstances,
enzyme offers two alternatives which I'll also point you to later but shallow is the one you should
use as often as possible because one thing shallow does is it renders the component with all its content
but the content isn't deeply rendered.
So the navigation items component here has navigation item components but these are only rendered as
placeholders,
the content of them isn't rendered and that of course again is important for creating isolated tests
where we don't then render a whole sub tree of components,
we just want to render this component and know what's inside of it without rendering everything which
is nested inside its included components.
So shallow is the method to use here
and now, we want to render that. So I'll create a constant which I'll name wrapper,
the name is up to you but wrapper is often used,
where I will call a shallow and now I'll pass navigation items as a react element.
So for that, I first of all need to import this, I need to import navigation items from
and that is from the navigation items javascript file which is living next to our navigationstest.
javascript trip.
With that we can render this here as jsx
and that's important,
we pass jsx to the shallow method. For this to work,
as always we of course need to import react then because no matter if it's a test or not, the jsx
code needs to be converted to its react create element alternative.
So now we're shallowly rendering this and we're storing the result in this wrapper constant,
now we can have a look into the wrapper in this test. And that's the last part of testing, we now
our expectation, for that we use another method which is made globally available by jest, the expect method.
Inside expect, we define our, the thing we want to check
so here I want to check if the wrapper contains a certain element.
Now on the wrapper, we can again use a utility function provided by enzyme defined method,
this allows us to look into the wrapper and see if it contains a certain content
and here I want to find a navigation item.
So we need to import this too, I'll import navigation item from ./navigation item navigation item,
just like that and therefore here in the find method, I now want to find navigation item. Important,
this now is not a jsx element, it's this normal exported function from the navigation item file.
Now with that
imported, we expect
well we expect nothing right now,
we just say what is our thing we want to check,
we want to check if we find that, but what is our expectation then? You could say the expectation is that
we do find it
but tests are a bit more flexible than this.
You could expect that you'll find it only once or twice or that you don't find it, maybe you want to
test for the opposite
so here we have to change something to the expect call,
these are utility methods made available by jest. So we can expect to find the navigation item
as we said earlier, two times if we're not authenticated, so navigation item to half length is what we can
call now
and you see there are a couple of helper methods.
The length we expect to find is two,
we want to find two
so this is automatically added into an array
and we want to have this to have a length of 2.
Now it will have isAuthenticated set to false because we're not passing this prop, remember? We're
just shallowly rendering navigation items, we're not sending any props here.
Now if we render it like this, isAuthenticated is not passed and therefore will be treated as false.
So with that, this test should actually succeed.
Now let's find out how we can test it then.
For this let's have a look at the package.json
file and there, if we scroll all the way to the bottom a little, not all the way excuse me a little
bit below our dependencies,
we see the scripts section.
We know the start script,
this runs in the browser,
we'll see the build script soon,
now we need the test script. And we can run this with npm run test or just npm test actually, like start
it's a special script where we don't need to run command.
This will now execute all the tests and it will automatically scan for all tests files by looking at
the ending, test.js.
Now I never save this file, so I should do so now,
this will then automatically rerun our tests,
it's watching the test files.
This warning regarding the polyfill can be ignored,
more interesting is if I expand this that we have one passed tests suite, the tests suite is the described function
and one passed test in general,
that's the it test here, the it function.
So our test is passed as we have expected
and this is how we write a test for a component.
Now let's add some additional tests to this component before we then also dive into testing other things.