This course has been updated! We now recommend you take the Angular 9 Fundamentals course.
Transcript from the "Creating a Component Test" Lesson
>> Lukas Ruebbelke: I'm going to walk through the pieces in the component spec, as it's generated, and explain what it does, and how to work with it. So, the first thing that I do when I am creating a component spec, is I create my local test members. And so this is by default going to be two things, but I'm going to introduce one additional thing.
[00:00:26] So the first thing is, you want to define the component that you want to test, which is this case is going to be a ProjectsComponent. Good. Now we're getting a little thing here, it's like you haven't read a clear disk, like should it be a cost? Well, the answer is no, hang on.
[00:00:47] The next piece is your test fixture or your component fixture. And so what this is, is a ComponentFixture.
>> Lukas Ruebbelke: That holds your.
>> Lukas Ruebbelke: Component that you want to pass.
>> Lukas Ruebbelke: So, one other thing I'm going to bring in, is a debug element.
>> Lukas Ruebbelke: Here we go.
>> Lukas Ruebbelke: And now we are to the, what I would say is the most important piece the entire thing.
[00:01:39] And this is all your testing happens or the genesis of it happens in the test bin. And so everything that should go into create if you are going to create a component, that requires services that has modules. You have to find a way to instantiate that in essentially a vacuum.
[00:01:59] And so.
>> Lukas Ruebbelke: instantiate test bed. And this, I think the other team has done a really, really good job with this. So we're going to go beforeEach. And you could do this asynchronously, but I'm going to do it just in a synchronous before each block.
>> Lukas Ruebbelke: I think because a web packet doesn't matter too much, I suppose if you're doing lazy loading possibly.
[00:02:28] But as of yesterday, I hate lazy loading.
>> Lukas Ruebbelke: So, Test Bin creates testing modules. So the first thing we are going to do, is we say when you create a component or anything, there needs to be a module that it lives in. And within the module.
>> Lukas Ruebbelke: You need to create a module as if it were the real module.
[00:03:00] So, when you call test bit configure testing module, it's basically creating an ng module, just with some of the teeth taken out. So this is kind of a standalone mock module, that you get all of the Angular life cycles and the different things with it. So from here, you are going to pass in your configuration object for that.
[00:03:26] So obviously, declarations is going to be ProjectsComponent.
>> Lukas Ruebbelke: What I'm also going to call out here, and this is probably going to be one of the biggest issues that you're going to have. When you're building out a test, is getting the right imports. And so, I'll just hop back over here, and I know for a fact that we're using material.
[00:04:01] We have the forms module.
>> Lukas Ruebbelke: We have, I'm just gonna peek here for a second. And so, this is not super important in the sense of, if you're missing a module it's going to fail. I don't know how to do this. And so, figuring out the error messages like I am missing these particular things.
[00:04:20] So HTTP client module and yes this is, of you're using angular material, then you're also going to need the browsers animation module. So it's getting those dependencies just right. Now also in your declaration, if we look in our projects component template.
>> Lukas Ruebbelke: Low and behold, we have two additional projects or components that we're using.
[00:04:49] So, we need to declare these as well. So, ProjectListComponent and ProjectDetailsComponent. And so I believe this is everything, so one is what component are you working with? Does it have additional components underneath of it that you need to declare, so that it can substantiate them? And, are you relying on additional modules, so what components is this component relying on to even work.
[00:05:21] We'll see here though, that fixture still it's like hey, this is a TestBed this is not a TestFixture. So what we have to do, is chain a method call on here, which is createComponent. And then we pass in ProjectsComponent. All right, so now, the fixture's happy. Because we've created the test bed, and then, underneath of it, we've chained this 'createComponent'.
[00:05:57] Now, what I will do is, you can do this asynchronously as well, where you can do compiled components and then an asynchronous block. So this is, one will actually wait for some asynchronous event, like if you have an external template that needs to go load. And so this is why they split that out, for that reason.
[00:06:16] But, so you can compile components and then down here, create component, separate that. Generally, I would just do this all in a single block. But it's kinda six of one half, a half a dozen of another. Now that we have our fixture. Now we can get a reference to our component.
[00:06:38] So we'll go component,
>> Lukas Ruebbelke: = fixture.componentInstance. And so now we have access to the component that we wanna test. From here, we can also get access to our debug element. So this is the actual, like an instantiated element of this component. So you actually have reference to essentially like a debug element, or a DOM element, with some debug stuff baked into it.
[00:07:06] So this is going to, unlike Angular JS, this allows you to actually do. I'm going to set this property, and I can test the DOM of that, and make sure that binding, that it's rendering correctly. And so, it doesn't really replace indent testing, but it's kind of a nice, it's like a poor-man's indent testing, which is kinda neat.
>> Lukas Ruebbelke: debugElement. And then we're going to do one other thing.
>> Lukas Ruebbelke: We're going to call detectChanges. Now, why this is happening, is when you create a component in a TestBed, it doesn't automatically trigger change detection. So for instance, if you change a property on your component and you want to verify that the DOM is updated.
[00:08:04] Well, Angular by default does not automatically trigger change detection in a test environment, because what they want to do is allow you do insertion pre-binding and post-binding. So they basically are giving you control on saying, when I change this thing I can verify something here, pre-change and then post-change.
[00:08:26] And so typically by default, within you before each, you'll set everything up and then you'll trigger an initial detect changes. And so that is what is happening there, but we'll see in a test in a moment, that if you don't fire that. So if you change a property and then you say, well it should have updated the DOM, it will not so you manually force that.
[00:08:49] And so let me go on to the project's component, and here we have primary color. I don't really know what I was doing there, but it's convenient. And let me do one other thing. In
>> Lukas Ruebbelke: The template, I'm just going to create h1 tag, and I'm just going to line to this.
>> Lukas Ruebbelke: I think I'm done with this. All right, I'll do a Save. All right, so now into our spec, I can create a test. So within this, I could say, it should have a primaryColor of red.
>> Lukas Ruebbelke: And then we can just run a basic instruction on this.
[00:10:01] So we'll go, expect.
>> Lukas Ruebbelke: (component.primaryColor). So notice it's already picking it up. So, language services for the win, toBe('red'). Well let's set this to green real quick and just see what happens.
>> Lukas Ruebbelke: What do you know, expected red to be green. Well, really what I was hoping for is that actually red would be green.
[00:10:41] Easy enough, red save.
>> Lukas Ruebbelke: This is all easier when you have like dual monitors, so typically when you do that is just outrun this up, and I'll just set it ,and just issue coding. Green, green, green, you mess you're like it's red, but a fix is in like 60 seconds or oops, not done something.
[00:11:01] So this is why I'm having to kind of hop that in fourth here.