- An angular application has lots of components.
Some components are complicated.
They have a rich user interface with lots
of HTML and other components are more straightforward.
So for example, you might have a component
just has a few instance variables that are going to
be data bound into the HTML.
And in the HTML you might have a few buttons maybe,
which when you click the button,
it calls a function on your component
which modifies the values of the data inside the component.
So what you could do is you could actually
test that component, just like a regular class.
You could create an instance of the class manually.
And then on that object,
you can manually invoke its functions.
You know, as if the user had clicked a button,
well you can invoke the
on click button manually to simplify matters,
to simulate the user events.
And then you can say,
"Well, after I've called this function
"has my data inside the object been changed?"
So you can assert that the object state
afterwards is correct.
So you don't need the whole kind
of angular framework to test this class.
Just create a regular object, call its functions,
and see what the data looks like afterwards.
So we're gonna look at this approach first,
a simple component that you can test
just like a regular class.
And then later on, we'll see how to do full testing
when the situation gets more complex.
Well, we have an example.
If you're gonna do lesson 12, it's the first example.
I've got a demo application.
I created it using angular CLI,
and I added a class called toggle switch component.
It's a button.
Every time you click it, it changes its state.
Okay. So it goes, initially it's on.
Then you click it, it's off.
When you click it again, it goes on.
When you click it again, it goes off.
It toggles its state.
So in my toggle switch component,
actually, when it's created initially,
it has an on is on state of false, okay?
So the button is off at the moment.
Imagine there's an HTML button that we can click.
And here's my on click handler.
When the user clicks a button on the webpage,
it changes the property to be false or true.
So every time the user clicks some kind
of user interface button,
it'll toggle the state of my component.
I've got a property here called status.
It's a string.
It'll say the toggle switch is on or off.
This is one of these JavaScript interpolated strings
where you can have embedded expressions
based on the value of my is on property.
This status will either be the toggle switch is on
or the toggle switch is off.
When this component is rendered,
it actually renders itself as HTML
and the HTML has a button, okay?
And that button basically has a click event.
That click event, when you click this button in the UI,
it'll call the click function up here
to toggle the internal status.
Whenever an event occurs,
data binding is automatically re-executed.
So if you change the flag here
angular will automatically re-display the HTML.
So from the top then,
the HTML it says the status here is this function, okay?
So this is a property.
It'll call that function internally to get the status.
Toggle switch is off will be initially displayed there
and then a space and then a button.
The button has a click event.
This is how you handle events in angular.
You put the name of the event into parenthesis
and then you basically call your function in your component.
So when the user clicks this button
it'll invoke that function.
That function toggles the is on flag.
It'll be re-rendered.
And by the way, the label of the button is displayed here.
So we've got data binding here.
We've got two bits of data binding really.
Data binding to get the value
of the status to be displayed there,
and data binding to display the label of button, okay.
Which is there.
So the button is basically the opposite
of the current state.
If the toggle switch is off,
then this button will say turn on.
So if it's currently off the button will say
click me to turn it on again.
The state that you want to move into.
So that's my toggle switch component.
I render one of those in my application.
So let me show you the code
and then we'll look at the tests.
So here's the code for my example one demo app.
In my app folder we have a toggle switch component.
We've also got a banner component,
which we're gonna have a look at a bit later.
My toggle switch component, it has this code.
The code that we just looked at,
it links in an HTML template, which is here,
displays the status, toggle switch is currently off,
handles the click event.
And it displays a label on the button.
I've got a star sheet.
I could make it look beautiful if I wanted to.
And I've got a spec,
this is the unit test for my component.
So that's obviously the focus of our attention.
And we'll have a look at that in a moment.
Just one other thing, in order to instantiate
or to create one of those toggle switches,
I forgot to mention my component
has a selector app toggle switch.
So if I wanted to create one of these toggle switches
in my application, that's the selector that I use.
And I've done that in my app component.
My top level component app component in the HTML
it basically creates an instance of the toggle switch.
So if I show you here,
this is what the application looks like.
It's got quite a lot of bits going on.
And in there it basically creates an instance
of my toggle switch.
So most all the stuff that's happening.
This was actually the code generated by angular CLI
which is crazy really, but here I've created an instance
of my toggle switch component, plus this other
banner component that we're gonna have a look at later.
But for now that will create an instance
of my toggle switch component.
And that instance has this data and it has this HTML.
So that's the HTML we should see when
the application starts.
So if you wanted to do this yourself,
open a command window, in example one demo app.
Do an NPM install to download the libraries,
and then do an NG serve to actually
build the application and serve it in a web server.
And then open a browser, local host 4200.
And you can see here, this is my toggle switch component.
It has a status.
The toggle switch is currently off,
but I can turn it on.
The status displays the current flag value.
Actually I'll show the HTML first.
The status is what we just saw.
And the status says the toggle switch
is off at the moment.
And the button says click me to turn it on.
So that button label is here.
It's basically the opposite of the current state.
So when I click that button, the click event occurs.
It calls my click handler, changes the flag and then
re-displays the toggle switch component.
So it's currently on and I can turn it off.
If I click it, it'll turn it off,
and it's currently off.
So every time you click it,
the status and the labels switch, they toggle.
So how can I test that component?
Well, here's my spec.
Here's the test.
In toggle switch component spec ts.
This here is just regular JavaScript
and not using any angular specifics.
This is just purely creating an instance of a class,
call its functions, see the value of data afterwards.
I've got a few tests here.
Before each test, create a brand new instance
of my toggle switch component
which will be in the off state originally.
So let's verify that.
Let's verify that my toggle
switch component is initially off.
So in my component, it's got an is on flag that's public.
I'm expecting it currently to be off.
The status, the get status function
effectively should be toggle switch is off.
That's the status I expect to get back.
The button label should be turn on.
My component button label there,
remember that was a property in my component.
In my component, it had a button label property
and basically check in that that button label
property returned the correct value.
Did my button label property return turn on?
Okay, good.
What about if we click the button?
Well, when the button gets clicked
in the real webpage, in the real component
if this was actually run in a browser
when the user clicks the button, it'll call this function.
So what I can do is I can emulate that.
I can just call that function directly in my test
as if it was the user instigated action.
But I can just call that function manually
to simulate the click event
and then see how my component reflects that change.
So here, I'm going to take my component
which has just been recreated.
I'm going to simulate the user click in the button.
In other words, I'm gonna call this function
on my component manually.
After that the component should have toggled.
Its is on state should now be true.
Its status should now be toggle switch is on,
and the button label should now be turn off.
So after one click, my component
should now be in the on state.
After two clicks it should revert back to the off state.
Okay, well, I've actually got that test.
If you go into the full code here,
in my toggle switch component spec
I've got this third function down here.
Check that after two clicks, the component is off.
Okay. So here we go.
So I'm going to click once, click twice.
After that I'm expecting my component to be back
in the off state and its status should be off.
The button should tell me I can turn it
on by clicking the button.
Okay. So there we go.
So when you've got a simple component
and the simple component has some simple state
and some simple functions,
the simplest way to test it
would just be to call these functions directly
from your test and then check the values
of the properties afterwards to see
if they've been updated correctly
after the function has been evoked.
Okay, we've done that.
And we can see that those three tests are working fine.