So we had a look at how we test components,
let's now have a look at containers like the burger builder,
how do we test these?
The tricky part about containers is that they are connected to the redux store here,
the redux store has some external influence on this component.
If it weren't connected, testing it would just be very equal to the other components because then yes it
might have state but enzyme actually also has methods to handle this, just as we have setProps,
we also have setState to simulate different states in that component.
So the tricky thing really is the redux store,
now the good thing is we don't really need to test the connection of this container to the redux store,
we can rely on the redux store to work correctly, and then in the end we only receive data from the store
as props to this container.
So we're back to the previous world,
we can just simulate props in our tests because we want to simulate different outcomes in different
states of props anyways, so that we don't want to connect that to some real store,
we don't want to test if the store passes this correctly to the component, that's the job of the connect
method
and that's coming from a third party library,
we can rely on that to work correctly.
So what we really need to do is we need to get access to the component behind this container so to
say
and one convenient trick is to simply export this burger builder class,
so simply add the export statement in front of this.
This now gives us a named export
in this file, burger builder which gets access to this class which is just a react component and we still
have the default export
we still have in our app but now we can write a testing file, BurgerBuilder.test.js and simply import
the burger builder class here with the name export from ./BurgerBuilder.
This can now be rendered again with shallow and so on, just as we rendered the normal component because
it is just a normal component and we totally strip out the connection to redux which is what we want.
So now with that change here, we can go to the navigation items test file and also copy the set up regarding
enzyme and the adapter,
let me copy all of that over to the burger builder, get rid of the imports of the navigation items
here instead we're importing the burger builder in that file and now we can start writing tests
here.
We still do this with the describe function of course
so here we really are testing the burger builder and now to simulate this,
let's quickly have a look at what we could test here. If we have a look at this file,
it would be interesting to see if we actually have build controls here,
if the ingredients are nonexistent because we should only render that if ingredients are passed along.
So what we can do is we can go to that function, the describe function and we will need to import build
controls,
so let's add such an import already from ./ or let's go up actually to components burger build
controls and import from the BuildControls.js file.
And then here, I'll again add beforeEach function to set my wrapper up, therefore I need to add this
wrapper variable
before I do so and then beforeEach, wrapper should be equal to shallow again because I don't want
to do some deep rendering, I want to have an isolated unit tests as you should use it as often as possible
and I want to shallowly render burger builder here, just like that.
Now for that, we also need to import react as always, so import react from react.
Now we can write a test with the it function and there I will describe it,
so it should render build controls when receiving ingredients.
Now let's add as a second argument that javascript function that should get executed and now in there, I will
simply use my wrapper
and first of all set props and I want to set that ings prop
we're expecting to get.
so this prop we are checking here, that ings prop we're expecting to get. Here I'll set
ings equal to let's say a javascript object where I have salad, zero.
Now with that I can use expect and wrapper and find to find my build controls, not a jsx element, just
the type here and this should have a length of 1.
Let's save this file and also save the burger builder file to really export the class and in case
you're ever getting this error regarding app.test.js, remove the app.test.js file with which the project
started, it actually will mount your entire application fail due to using routing.
Now you should still get one error now, that this.props.onInitIngredients is not a function, this error
make sense because shallow will render your component here even though it doesn't deeply do that
and in the burger builder if you inspect it, you'll see that in componentDidMount,
we call this prop and this of course is not made available because we only set one prop, ings.
So to fix this, we have to add this as a prop,
now adding it with setProps won't do the trick because that is added or that is set after the component
has been instantiated, so that's too late.
We have to add it here onInitIngredients and I'll set it to an empty arrow function here, to
simply fulfill the requirement of passing a function.
Now with that if you save it, the test passes.
If we now pass ings to be null just to check the opposite, it fails
and this is an example which you of course may fine tune to your need to see how you can test containers.
You essentially strip out the component part and get rid of the connection to redux.
Now speaking of redux, how do we test that then?