Stephen: In the last section,
we threw down the three very core constructs
for our testing set up here:
describe, it, and expect.
Remember, describe is used to group together similar tests,
so since we have one test per file or per component,
one test file per component,
we use our top-level describe here,
and I'll explain what I mean by top-level describe
in a second, to say, "Hey, everything in this file,
all the tests we're about to to write
are about the component app."
Next we use it to test a single attribute of the target.
So we said our App component,
there's one thing that we care about this component
and we just care that it shows the correct text,
so inside of it we will make an assertion that says,
"I expect my component to have the correct text."
Again, the string here is just used as guidance
to someone who's reading our testing output.
Finally, we brought on the keyword expect.
Expect is used to test a very particular attribute
about our target, and again,
our target is the App component.
Okay, so let's go ahead and turn these keywords
into something actually usable,
something we can actually run here.
So the first thing I'm gonna do
is I'm gonna throw a little bit of code in here,
I'm gonna throw a second argument to describe.
Let's go ahead and add the code first
and then we'll talk about what's going on.
So I'm gonna add in a second argument
and it's gonna be a fat arrow function, like so,
so open parens, fat arrow, curly braces,
and then we'll put in our function body right here.
Now, I'm gonna take everything from the it block on down,
I'm gonna cut it, and I'm gonna put it
inside of that function body, so now I've got describe,
I'm describing the App component,
and then as a second argument
I'm passing a function in, okay?
Let's go ahead and repeat this process one more time,
but this time with the it block,
so its first argument is gonna be a string
and then the second argument, so comma,
is gonna be another fat arrow function.
I'm gonna open up the function body like so,
and I'm gonna copy-paste, or cut and paste,
the expect statement down here into the it block.
And then I'm gonna do just a little bit of code cleanup
but I'm gonna leave a lot of new lines in here
just to show kinda grouping
of all the different stuff that's going on.
We'll come back through later on
and remove these extra new lines.
Okay, so what we did here is we just refactored
our describe, it, and expect,
to how we normally will write our specs, all the time.
All of our specs are always gonna follow a syntax like this,
describe takes the first argument of a string
and the second argument of a function,
and inside that function are all of the specs
that are grouped with this described block of App.
So inside of this function we're gonna have
a bunch of it statements,
all of them are gonna describe
some specific behavior of App.
So in this case we've got one it statement that says just,
you know, we've said this several times now,
it shows the correct text.
Then we repeated the same process
by passing in another function to it,
and inside of this one we put our expect statement in here.
So you might be asking, "Okay," like, "Sure,
functions, we're putting some it calls
inside of a describe block function," blah, blah, blah,
you know, all this stuff.
What's the purpose of this?
Why are we doing this?
And the answer to that is that this is a core part
of how Mocha runs tests.
So when Mocha first executes
and runs this App test file right here,
the tests are not immediately ran,
so when this file gets parsed, it goes into Mocha,
Mocha reads all the code in here,
the code is not immediately executed,
instead, Mocha takes record of all of the functions
that we declared
and passed into these describe and it blocks,
and the purpose of that is that so Mocha
can kind of cue these tests up to run in the future,
and it's by doing this kind of queuing up
that it can safely execute our code,
which might be throwing, like,
tremendous errors all the time, right?
Let's say that in one of our it blocks we throw a new error.
Now, in normal JavaScript,
if we just kind of executed this new error,
our entire testing suite would just crash from the get go,
but because we wrapped it inside of a function,
Mocha can safely execute this function right here
and say, "Hey, if this function right here,
if it throws an error, don't worry about it,
I'm a testing suite, I expect it to maybe throw an error,
and if it does, I can handle that,
it just means the test failed."
So again, the purpose of wrapping all of our specs
with these functions right here are so that Mocha
can safely execute all of our tests
without worrying about some error being thrown
by some, you know, junk code
that we might have happened to write.
Okay, so let's go back to our expect keyword here.
So we've kind of fleshed out our describe statement,
we've fleshed out our it statement,
now we need to flesh out our expect statement.
I'm gonna pull up a quick diagram
just to kind of explain what we're about to do
with the expect statement.
Bear with me for one second.
Here we go.
Okay.
So this is what I call the anatomy of an assertion
or the anatomy of an expect statement.
So again, the purpose of an expect statement
is to make one very single declarative test
about some target, in our case, the component.
So the syntax of all these assertions
that we're gonna write are gonna look very similar
to this right here,
there's just gonna be some very slight changes over time
for different specs that we want to write,
but in general, we're always gonna have very similar syntax
to what we have right here.
The purpose of this assertion
or the syntax that we see here
is to make something that can almost be read
like plain English.
So if we read this line of code,
ignore the arrows and black text all over here,
let's just read the red line of code,
like, it's just a very simple sentence,
we expect component to have class comment-box.
So if we kinda interpret that
as this very plain English, you know,
let's forget that this is code,
let's just kinda read this as English right now.
I expect my component to have
the CSS class comment-box, and that's it,
that's all an assertion is doing.
We use assertions like this
to test very particular attributes of our target
which, in this case, is component.
So now that we have a better idea
of what the expect statement is for,
let's talk about all the individual parts of it.
Expect is a function that returns an object,
and you can see that it is an object
because we're kinda chaining on
these additional properties here.
So again, expect is a function.
We pass into expect the thing that we want to test,
the thing that we want to make an assertion about,
probably 90% of the time
when we're testing React components,
we're going to be testing the component itself.
So vast majority of the time, the first argument here
and the only argument that we'll see
in our expect statements is going to be component.
The second part of of an assertion is the matcher.
This to.have.class right here,
and this is what tells Mocha, like,
essentially how we want this test to behave,
what we want to test exactly.
In this case we said, "I want this to have class,"
and then the thing, the value that we expect
over here on the end.
This matcher right here, this to.have.class
is probably the most challenging part of testing
'cause there are a tremendous number
of different matchers out there in the world
that we can make use of,
and I've wired up several additional ones
inside of our testing boilerplate here.
As we start working on our first project,
our first test, standalone feature, excuse me,
we're going to look at some documentation and make sure
that it's very clear to you
where these matchers are coming from
and what all the matchers that are available are,
and how to get access to them.
So if this part right here looks weird or confusing,
don't worry, we're gonna delve into that
in great, great detail.
Finally at the end, this one is perhaps
a little bit more expectable, the value that we expect.
So in this kind of made-up example right here
we're expecting our component to add the class,
specifically the string comment-box.
So behind the scenes
expect is going to take this matcher right here,
take this string and see,
"Hey, does this component right here,
does it have the class comment-box?"
If it does, great, expect passed, everything's green,
that means our code is good to go.
If component does not have class comment-box,
that means our test failed
or we refer to it as being red, red means failed,
and it means that our code is not working as intended,
that would show up as a spec failure.
Okay, so with this kind of idea of a matcher,
let's go ahead and add our first matcher to our code,
so we've got expect right here,
we need to pass something into it,
the thing that we want to test,
so the thing that we wanna test is going to be component.
Now, we haven't defined component yet,
you'll see that we haven't used component anywhere else
inside this file, so we are gonna have to define component,
we'll do that in just a second.
So remember, the thing that I cared about inside of my app,
which is what we're testing,
we're testing the App component,
the only thing that I really cared about
was that it had the appropriate text.
Remember we said, "I want to make sure this thing
is showing the correct text."
So I'm gonna use a matcher here, and again,
we're going to walk through a ton of different matchers,
so this is just one that I'm pulling off
at the top of my head here, so to speak,
we'll talk about where these are all coming from later.
I'm gonna say to.contain,
and then the text that I expect it to contain,
which in this case is, "React simple starter," like so.
So again, this is something that we could read
like plain English, from left to right.
I expect my component
to contain the text, "React simple starter."
One thing I wanna point out here,
make sure after the expect call right here,
make sure you've got a dot between the two,
so we should see expect component.two.contain,
and then another function call,
no dot between contain and the set of parens right here.
This is a really common area to make small typos
when you're getting started with writing tests
so do make sure that you've got
the correct number of dots in here.
In general, the testing or the errors that you'll see
if you make a mistake like this
tend to be pretty straightforward.
You'll see a error on the terminal
and it'll say something like,
"Unexpected token somewhere in here."
Okay, so again, the last thing we need to do here
is create our component, an instance of our App component.
Now, as you might guess,
at the very top here with this renderComponent helper,
we're gonna use this to make our component.
So I'm gonna put inside of the it block,
I'm gonna say, "Create an instance of App,"
and so we'll say const component = renderComponent App.
Now, what's going on here really comes down
to how renderComponent works,
and again, this is one of the helpers I set up for us,
it's something that we're gonna come back to in the future
and talk about exactly how it's working, but for right now,
let's just kinda run with this renderComponent thing.
All right, so I'm gonna save this file,
I'm gonna flip back over to my terminal
and I'm gonna run my testing command.
So this is a command that's already been set up,
you know, again, this is a part
of the boilerplate package, and we're gonna talk exactly
about how the command works again in the future.
So let's go ahead and just run it, see our test run,
and we're gonna expect it to pass.
So I'm gonna run npm run test;watch.
There's gonna be some output here as everything warms up.
And then we see App shows the correct test,
text, excuse me, and we have one test that is passing.
Terrific.
So that means that the spec that we just wrote is passing.
Let's go ahead and continue the next section
where we're going to walk
through this kinda testing output right here,
and we're also gonna see how we can make a spec fail.
So I'll see you in the next section.