- In the previous section
we had a look at the simple application
which contained a header component.
It was an example for HelloWorld.
Let's just take a quick reminder.
Here it is.
In the source folder, underneath app
there was a header component.
It was a very simple example.
And we saw what the test script looked like.
And we discussed the purpose of the
of these various things.
Creating a dummy module that knows about my component,
compiling the HTML into JavaScript for that component,
asking the test bed to create an instance of that component.
It gave us back a fixture, and that fixture object,
it wrapped up the component.
The component enabled us to write tests like this.
So, that was the headercomponent.
And that we ran the tests, and tests looked like this.
The headercomponent was created successfully.
But, also notice, the appcomponent also had some tests.
So what, what we're gonna do
in this section is have a look at the, the tests
for the appcomponent and understand what's going on.
Okay. So let's go back
into the source code and for the appcomponent.
I think the first place to start would be to look
at the actual code for the appcomponent.
Okay. So let's have a look in there, my appcomponent.
So first of all, it is a class and it does have data.
The purpose,
in fact, there were two purposes for, for component class.
One is to have data to be displayed.
And the other thing is to handle events
from its HTML template
because every component has an HTML template
to display the data and to generate events.
So, let's have a look at the HTML file to see how
it displays this type of property.
This is the HTM template,
and it says, whatever the title was,
what was the title actually?
The title was HelloWorld.
Of course it was.
HelloWorld is the title property.
So data binding, grab the value of title from the component.
HelloWorld app is running.
Also, it instantly did my headercomponent
that we just looked at.
Okay, so that's simple enough.
Now let's have a look at the spec.
So this is the spec that was generated
by angular CLI, I haven't embellished this.
This was actually generated by the angular CLI tool.
So from the top import the test bed class
from Angular core testing, the test bed is kind of like,
it enables us to create a
a dummy module that contains our components for testing.
Before each test, there were three different tests here.
As you can see online, 14, 20, and 26.
There were three tests.
We kind of knew that anyway
because there were three tests here.
Before each of those tests, it executes this code.
It asks the testbed to create a testing
module that knows about our component.
Okay. So when that component has been loaded
into the test model, compile that component.
So, remember what that function does.
Each component has an HTML template
but that HTML template actually gets compiled
or converted into pure JavaScript.
So this is what would normally happen
doing compilation, that's what's happening here.
It basically converts the HTML
into pure JavaScript to be executed.
So by this, at this point, now the testbed now
has created a module that knows about my appcomponent.
Okay. So it'll, recreate,
it'll do that before each test.
And the first test, it goes to the testbed.
Please create an instance of appcomponent.
Remember we get back a fixture object
and the fixture object is a wrapper
to the component.
So this here is the appcomponent
and we can verify did the appcomponent,
does the app component exist?
The appcomponent should exist.
Okay. And it does.
Okay, so should create the app, the order
in which you see these tests being displayed
to you isn't necessarily the order
in which they appear in the script, should create the app.
That's the first test done.
What about the second test?
The application component should have the title. HelloWorld.
What we're establishing here is,
does my component have a title,
Is an object, does it have a title property?
HelloWorld.
That's what this test does.
Let's see how this works.
So again, create the component, gives us back a fixture.
That fixture is a wrapper to the component
gives us back the component.
That is an instance of my component class.
App is basically the instance of my component.
Okay? Check that the application object has a
title equal to HelloWorld
because that's the value that is in there.
And it should be correct.
Does my application component have a title property set
to HelloWorld?
It should have a title.
HelloWorld.
Let's have a look, and it worked.
Good.
What about the third test?
The third test here.
Oh, not only does it have a title property
but it should render that title property correctly
in the HTML.
It's one thing for the component to
have the right data, it's another thing to see
if the HTML template rendered it properly,
because it should have done.
If my component has this title, then the HTML
our HTML template should render it properly.
It renders it as well,
there should be something like
HelloWorld app is running.
Okay. There should be something that looks
like that in the HTML.
That's what we're testing for.
So let's go back and have a look.
Okay, so there's an element of repetition here.
That statement seems to appear
at the beginning of each test.
So that could have been factored out actually into a
before each.
Anyway, create another instance
of the component and give me back the fixture wrapper.
Remember what the fixture detect changes statement does.
The component has data.
That data is gonna be displayed
in the HTML template in order for that data binding to occur
you've gotta call this function.
Okay. So if you wanted to put a comment here.
When you say fixture detect changes, what it means is,
tell angular to do data binding.
In other words,
in other words, the HTML
is updated
with current data from the component.
Okay? So basically it, it basically forces the
angular engine to execute data binding.
So in my HTML, when there's data binding here
in order for that data binding to actually happen
you have to say fixture detect changes.
That's a really bad name for it, a better name
would've been do data binding.
Take the component and basically update the HTML
with the current value of the title.
So that should, after my detect changes function
called that should now say, HelloWorld app is running.
That's what should have happened.
Okay, so now this is how you can actually check
that it happened.
You've got a fixture object
and the fixture object points to the component.
What you wanna do now is you wanna say
look at the native HTML
for that component to see what was actually rendered.
And that's what this does, fixture native element.
It says, go to my component and give me the, you know
like the, the HTML inside that component from the, like the
the top of the HTML, it gives you back an HTML element.
Basically, the component that has been rendered as HTML
it gives you back the HTML.
When it says compiled here
it means the HTML that has been generated effectively
what HTML was generated here.
It'll give you back pointer to the div effectively.
Okay, so we can now say,
we can now check the content of that div to say
does it contain the right span, for example?
So the native element, you get back basically pointer
to the top of your, of your rendered content.
So now we're in the kind of HTML sphere
of influence take that rendered HTML and query selector.
That's just a standard HTML five function,
search in my HTML
search for an element that has this property.
I'm looking for an element that has a CSS class of content.
And in that element
there should be a descendant element called span.
I'm looking for a span
inside something with a CSS class of content.
Okay, so that's gonna find, this here is an element
with the CSS class of content and here's the span inside it.
Okay. So that will basically find that span element.
It could be null.
So in type script
the question mark is called the safe navigation operator.
It says as long as that isn't kind of null or undefined.
In other words, if it existed
give me the text content of that span.
So that will obviously give you the text content,
after having been data bound.
So it'll say, HelloWorld app is running.
That's the text that we get back inside the span.
This is starting to take shape now.
Let's check that content.
That content should contain this text.
HelloWorld app is running.
Okay, so from the top
create the component, update data binding
so the HTML is updated with the correct data.
Give me back that content of the component as HTML.
And then inside that HTML search for sub content,
find the div as it happens with the CSS class of content,
find the descendant element, the span, get its text content
and verify that it contains HelloWorld app is running.
And it does indeed to say, HelloWorld app is running.
So when we run the tests, it all works beautifully.
And that's that one there.
So just to play devil's advocate
I'm gonna deliberately break my HTML
and I'm gonna change this to be is, is
definitely running.
Okay, so now the test will fail.
That's the test of the span that we actually have.
This is the text of the span it was looking for
and it'll now fail this test.
Okay, so it's failed the test in my app component suite.
The test that failed should render title,
that failed.
In my test I was expecting this,
well, that's basically what appeared
and this is what I was hoping it did be, okay.
So I can see what the problem is.
I can see if there's a bug in my HTML
let's fix the bug in my HTML, save it.
It automatically reruns the test
because it's running in watch mode.
So that should now work.
You just need to give it a moment
and it's worked beautifully.
Okay, so that's actually, you know,
quite a realistic example
of how to get started testing components.
What we're gonna do in the next lesson is to
dig a lot more into detail, to handle things
like events and other features that you can have
in an android application.