1 00:00:06,540 --> 00:00:08,610 - Over the last few sessions, 2 00:00:08,610 --> 00:00:11,580 we've been having a look at the demo application, 3 00:00:11,580 --> 00:00:14,460 which had two levels of components, 4 00:00:14,460 --> 00:00:16,290 a high level app component, 5 00:00:16,290 --> 00:00:20,250 that passed data into a lower level product component. 6 00:00:20,250 --> 00:00:22,440 So, here's the lower level product component. 7 00:00:22,440 --> 00:00:24,870 It's in lesson 12, example two. 8 00:00:24,870 --> 00:00:26,580 It's the demo app we've been looking at 9 00:00:26,580 --> 00:00:28,680 for the last couple of sessions. 10 00:00:28,680 --> 00:00:31,890 So, a product component receives an input 11 00:00:31,890 --> 00:00:36,120 from its parent and it renders one product. 12 00:00:36,120 --> 00:00:38,910 It can pass an output event back to the parent 13 00:00:38,910 --> 00:00:41,610 to say a sale has just occurred. 14 00:00:41,610 --> 00:00:46,533 So, we have an application component that sits here. 15 00:00:48,210 --> 00:00:52,140 And the application component has some product data 16 00:00:52,140 --> 00:00:55,740 that it basically passes in as an input. 17 00:00:55,740 --> 00:01:00,570 And it can receive an event like that as an output, 18 00:01:00,570 --> 00:01:04,530 which you can then update sales on the webpage. 19 00:01:04,530 --> 00:01:05,363 Okay? 20 00:01:05,363 --> 00:01:07,530 So, we've been focusing our efforts 21 00:01:07,530 --> 00:01:10,800 on the product component in the last session. 22 00:01:10,800 --> 00:01:12,300 What we're gonna do now is have a look 23 00:01:12,300 --> 00:01:15,210 at how to test the application component itself. 24 00:01:15,210 --> 00:01:17,190 So, here's the application component. 25 00:01:17,190 --> 00:01:19,980 It holds an array of products 26 00:01:19,980 --> 00:01:23,253 and it gets notified of sales, so we can display them. 27 00:01:24,690 --> 00:01:27,360 That's the application component. 28 00:01:27,360 --> 00:01:29,580 How does that get rendered? 29 00:01:29,580 --> 00:01:31,560 Quick reminder, here we go. 30 00:01:31,560 --> 00:01:34,170 So in the app folder, 31 00:01:34,170 --> 00:01:36,543 here's my application component code. 32 00:01:37,620 --> 00:01:40,233 It has a bunch of products, 33 00:01:41,430 --> 00:01:42,993 which are initialized here. 34 00:01:44,010 --> 00:01:47,130 And the HTML, remember we've seen this before. 35 00:01:47,130 --> 00:01:50,010 In the HTML we iterate through those products. 36 00:01:50,010 --> 00:01:52,710 For each product we pass each product 37 00:01:52,710 --> 00:01:55,560 into a product component. 38 00:01:55,560 --> 00:01:58,980 So, app product is the selector 39 00:01:58,980 --> 00:02:02,370 for product component to display one product. 40 00:02:02,370 --> 00:02:04,320 We pass in an input parameter 41 00:02:04,320 --> 00:02:07,860 to say here's the value for your product input. 42 00:02:07,860 --> 00:02:11,340 And, if you generate a sale event 43 00:02:11,340 --> 00:02:13,980 then I will handle it in my function, 44 00:02:13,980 --> 00:02:16,620 me being the application component 45 00:02:16,620 --> 00:02:18,360 and you being the product. 46 00:02:18,360 --> 00:02:21,270 So, when it says app product here, 47 00:02:21,270 --> 00:02:23,280 just to remind you before we start looking at 48 00:02:23,280 --> 00:02:26,280 testing in this section. 49 00:02:26,280 --> 00:02:28,740 App product, remember, is the selector 50 00:02:28,740 --> 00:02:30,003 for product component. 51 00:02:30,930 --> 00:02:32,553 So, there it is. 52 00:02:33,990 --> 00:02:36,540 So in my application HTML, 53 00:02:36,540 --> 00:02:39,510 when I say app product, it's going to create 54 00:02:39,510 --> 00:02:42,780 an instance of my product component. 55 00:02:42,780 --> 00:02:45,667 My product component expects a product input parameter. 56 00:02:45,667 --> 00:02:48,360 "Give me a product object." It says. 57 00:02:48,360 --> 00:02:51,690 And we say, "Have this one." 58 00:02:51,690 --> 00:02:52,653 That's the input. 59 00:02:53,820 --> 00:02:57,603 My product component can generate a sale event. 60 00:02:58,560 --> 00:03:01,390 If my component generates a sale event 61 00:03:02,460 --> 00:03:04,860 then I handle it in my application component. 62 00:03:04,860 --> 00:03:07,177 I say, "Oh, by the way, if you handle, 63 00:03:07,177 --> 00:03:10,447 "if you emit a sale event, I will call this function 64 00:03:10,447 --> 00:03:14,040 "in my application component to handle that event." 65 00:03:14,040 --> 00:03:15,750 In my application component, 66 00:03:15,750 --> 00:03:18,900 I will handle sale events like so. 67 00:03:18,900 --> 00:03:22,320 Okay so, we've seen how all that works. 68 00:03:22,320 --> 00:03:23,610 What we haven't yet seen 69 00:03:23,610 --> 00:03:26,370 is how to test the top level component. 70 00:03:26,370 --> 00:03:28,773 How can we test the application component? 71 00:03:29,880 --> 00:03:31,350 Okay so, here it is. 72 00:03:31,350 --> 00:03:34,530 Here's my app component spec TS. 73 00:03:34,530 --> 00:03:36,600 So, generally when you're, 74 00:03:36,600 --> 00:03:40,710 when you have a top level component that you wanna test 75 00:03:40,710 --> 00:03:42,930 that has lower level components, 76 00:03:42,930 --> 00:03:44,220 as a general rule of thumb, 77 00:03:44,220 --> 00:03:47,220 you should consider a stubbing the lower level component. 78 00:03:47,220 --> 00:03:48,810 And that's what I've done here. 79 00:03:48,810 --> 00:03:52,680 I've defined a stub implementation for product, okay? 80 00:03:52,680 --> 00:03:55,587 Because, I'm testing my application component 81 00:03:55,587 --> 00:03:59,160 and I don't really care about product component. 82 00:03:59,160 --> 00:04:01,470 So, I've created a product stub component. 83 00:04:01,470 --> 00:04:04,740 Basically, in my application HTML, 84 00:04:04,740 --> 00:04:09,740 now, anywhere it says, "Give me a product component." 85 00:04:10,410 --> 00:04:13,200 Instead of creating a real product component, 86 00:04:13,200 --> 00:04:16,380 it'll create a stub product component. 87 00:04:16,380 --> 00:04:18,783 It has an input parameter for product. 88 00:04:19,980 --> 00:04:22,290 It can generate the sale event, 89 00:04:22,290 --> 00:04:24,420 but it doesn't have any template. 90 00:04:24,420 --> 00:04:27,090 So effectively, it's like an empty box. 91 00:04:27,090 --> 00:04:30,240 My application component will render, for each product, 92 00:04:30,240 --> 00:04:33,423 it'll render one of these and it's just an empty stub. 93 00:04:34,710 --> 00:04:37,440 So, what we need to do then is next step 94 00:04:37,440 --> 00:04:39,480 when you're testing components, 95 00:04:39,480 --> 00:04:42,090 you need to set up a test module. 96 00:04:42,090 --> 00:04:44,790 Remember in Angular, a module is a box 97 00:04:44,790 --> 00:04:48,300 of components that, you know, it needs to know about. 98 00:04:48,300 --> 00:04:52,890 So, the test bed, configure test module adapter. 99 00:04:52,890 --> 00:04:56,100 I'm gonna give it my main application component 100 00:04:56,100 --> 00:04:58,710 and my stub product component, okay? 101 00:04:58,710 --> 00:05:01,740 So, it knows about those two components now. 102 00:05:01,740 --> 00:05:03,960 Remember the compiled components function? 103 00:05:03,960 --> 00:05:05,950 When you call compiled components 104 00:05:07,200 --> 00:05:09,600 it basically converts any HTML 105 00:05:09,600 --> 00:05:11,280 that might be in your templates. 106 00:05:11,280 --> 00:05:13,320 It converts into pure JavaScript, 107 00:05:13,320 --> 00:05:16,803 so that these components are now ready to be instantiated. 108 00:05:17,850 --> 00:05:21,180 Okay then, so let's have a look at a test. 109 00:05:21,180 --> 00:05:23,880 I'm gonna check that when my application component 110 00:05:23,880 --> 00:05:27,270 is rendered, it creates the appropriate number 111 00:05:27,270 --> 00:05:29,580 of child product components. 112 00:05:29,580 --> 00:05:31,533 So, let's see what's going on. 113 00:05:32,460 --> 00:05:36,390 Go to my test bed and create an application component. 114 00:05:36,390 --> 00:05:39,510 So, remember what happens. 115 00:05:39,510 --> 00:05:41,433 That will create a fixture object. 116 00:05:43,080 --> 00:05:45,210 And that fixture object is a wrapper 117 00:05:45,210 --> 00:05:47,730 for our our application component. 118 00:05:47,730 --> 00:05:49,860 So, here's our application component. 119 00:05:49,860 --> 00:05:52,530 And as we know, because we've seen this code 120 00:05:52,530 --> 00:05:53,820 a few times now, 121 00:05:53,820 --> 00:05:55,530 when we create the application component, 122 00:05:55,530 --> 00:05:58,650 it has three products inside it, okay? 123 00:05:58,650 --> 00:06:01,050 So, if I draw this, like so, 124 00:06:01,050 --> 00:06:03,073 here's my application component. 125 00:06:03,073 --> 00:06:06,480 Three products, you know, just data. 126 00:06:06,480 --> 00:06:09,183 Those are the products in my array. 127 00:06:10,200 --> 00:06:13,203 So, the fixture available variable is this object. 128 00:06:14,130 --> 00:06:17,100 Detect changes, we've seen that a few times now. 129 00:06:17,100 --> 00:06:19,590 When you say detect changes, 130 00:06:19,590 --> 00:06:22,500 it basically updates the HTML, okay? 131 00:06:22,500 --> 00:06:24,420 So, it does data binding. 132 00:06:24,420 --> 00:06:29,420 So, whatever HTML I had for my application component, 133 00:06:29,520 --> 00:06:32,010 it will be updated with that data. 134 00:06:32,010 --> 00:06:33,990 Now, what would happen at that point? 135 00:06:33,990 --> 00:06:35,130 What happens at that point? 136 00:06:35,130 --> 00:06:36,420 Think about this. 137 00:06:36,420 --> 00:06:39,900 In my HTML, from my application component, 138 00:06:39,900 --> 00:06:43,860 this should now have created three instances of this. 139 00:06:43,860 --> 00:06:45,110 It should have basically, 140 00:06:45,990 --> 00:06:48,870 instantiated three app products. 141 00:06:48,870 --> 00:06:50,970 That app product now corresponds 142 00:06:50,970 --> 00:06:53,400 to my stub product component. 143 00:06:53,400 --> 00:06:55,590 So, it'll receive a product 144 00:06:55,590 --> 00:06:58,290 and it'll potentially emit a sale. 145 00:06:58,290 --> 00:07:01,050 But, it's gonna instantiate a stub product 146 00:07:01,050 --> 00:07:01,883 for each one of those. 147 00:07:01,883 --> 00:07:03,600 And there should be three of them. 148 00:07:03,600 --> 00:07:06,390 My array of products has three products, 149 00:07:06,390 --> 00:07:08,940 so there should be three of these 150 00:07:08,940 --> 00:07:13,680 created inside my generated HTML. 151 00:07:13,680 --> 00:07:14,580 Right. 152 00:07:14,580 --> 00:07:17,430 Now then, here's something you haven't seen before. 153 00:07:17,430 --> 00:07:18,723 When you go to fixture, 154 00:07:19,560 --> 00:07:23,880 you can examine the static HTML that was generated. 155 00:07:23,880 --> 00:07:27,930 We've seen a function called fixture.nativeElement. 156 00:07:29,046 --> 00:07:31,110 When you say fixture native element, 157 00:07:31,110 --> 00:07:34,110 it gives you the raw HTML, okay? 158 00:07:34,110 --> 00:07:38,340 So if you call the native element function, 159 00:07:38,340 --> 00:07:43,200 it'll give you the raw HTML generated by the component. 160 00:07:43,200 --> 00:07:46,920 But there's a more useful function, called debug element. 161 00:07:46,920 --> 00:07:50,610 And what that does is it doesn't give you the raw HTML. 162 00:07:50,610 --> 00:07:54,000 It gives you the actual component tree itself, 163 00:07:54,000 --> 00:07:57,510 including the product component, not just the HTML, 164 00:07:57,510 --> 00:08:00,000 but the components that generated them. 165 00:08:00,000 --> 00:08:04,020 So debug element, the debug element function 166 00:08:04,020 --> 00:08:07,440 gives you access to the actual component tree. 167 00:08:07,440 --> 00:08:10,923 There should be three products in that product tree. 168 00:08:11,760 --> 00:08:14,850 What's the debug element function property? 169 00:08:14,850 --> 00:08:16,830 So, the debug element property, 170 00:08:16,830 --> 00:08:20,100 it gives us access to this actual component tree. 171 00:08:20,100 --> 00:08:23,100 And that component tree has high level 172 00:08:23,100 --> 00:08:26,100 query capabilities, based on Angular. 173 00:08:26,100 --> 00:08:28,440 So this basically, is Angular aware. 174 00:08:28,440 --> 00:08:29,970 It isn't just HTML. 175 00:08:29,970 --> 00:08:32,730 It allows you to look at actual components 176 00:08:32,730 --> 00:08:36,240 and so on, in your actual component hierarchy. 177 00:08:36,240 --> 00:08:40,170 For example, you can call upon this debug element. 178 00:08:40,170 --> 00:08:43,020 You can say, "Query all." 179 00:08:43,020 --> 00:08:44,495 And then, you can give it a selector. 180 00:08:44,495 --> 00:08:49,495 By, by the way, is another class provided by Angular. 181 00:08:49,890 --> 00:08:54,890 When you say By.css, you can give it a CSS selector. 182 00:08:55,050 --> 00:09:00,050 It means, if you say this, it means element name. 183 00:09:00,360 --> 00:09:04,140 Or there's a dot to represent the CSS class. 184 00:09:04,140 --> 00:09:07,500 Or you could use a hash to represent an ID. 185 00:09:07,500 --> 00:09:11,310 But this means, find elements called app product 186 00:09:11,310 --> 00:09:13,710 in my actual component tree, you know, 187 00:09:13,710 --> 00:09:15,870 before they've actually been expanded. 188 00:09:15,870 --> 00:09:19,680 So, fixture.debugElement gives me access 189 00:09:19,680 --> 00:09:22,200 to the complete dom structure generated 190 00:09:22,200 --> 00:09:24,300 by my component in there. 191 00:09:24,300 --> 00:09:27,690 I can find all occurrences of elements 192 00:09:27,690 --> 00:09:32,370 that have this element name, app product. 193 00:09:32,370 --> 00:09:34,113 So what that's going to find, 194 00:09:35,460 --> 00:09:37,503 it's going to find these elements, 195 00:09:38,370 --> 00:09:40,503 these elements here, okay? 196 00:09:41,460 --> 00:09:42,990 There would be three of those, 197 00:09:42,990 --> 00:09:45,030 because there were three products. 198 00:09:45,030 --> 00:09:47,790 So it actually gives me access to the actual, 199 00:09:47,790 --> 00:09:51,120 you know, component hierarchy, app product. 200 00:09:51,120 --> 00:09:52,110 That's the element. 201 00:09:52,110 --> 00:09:54,570 I'm looking for an element called app product. 202 00:09:54,570 --> 00:09:57,633 And by the way, there should have been three of them. 203 00:09:58,770 --> 00:10:01,530 All right so, using this technique, 204 00:10:01,530 --> 00:10:03,180 you can, using debug element, 205 00:10:03,180 --> 00:10:04,740 I think is probably the main thing here. 206 00:10:04,740 --> 00:10:06,450 It gives you access to the, you know, 207 00:10:06,450 --> 00:10:08,520 to the complete dom structure, 208 00:10:08,520 --> 00:10:11,640 or to the complete component structure of your component, 209 00:10:11,640 --> 00:10:12,930 so that you can check basically, 210 00:10:12,930 --> 00:10:16,410 how many instances of my child component 211 00:10:16,410 --> 00:10:17,850 did it attempt to create. 212 00:10:17,850 --> 00:10:19,500 And there should have been three of them. 213 00:10:19,500 --> 00:10:21,900 So, have a play with this. 214 00:10:21,900 --> 00:10:24,240 Have a play with the debug element function 215 00:10:24,240 --> 00:10:27,180 and try to get familiar with this approach. 216 00:10:27,180 --> 00:10:29,400 This is basically how you locate elements 217 00:10:29,400 --> 00:10:32,943 using the tag name represented by your component.