1 00:00:06,510 --> 00:00:09,420 - An angular application has lots of components. 2 00:00:09,420 --> 00:00:11,040 Some components are complicated. 3 00:00:11,040 --> 00:00:13,230 They have a rich user interface with lots 4 00:00:13,230 --> 00:00:16,860 of HTML and other components are more straightforward. 5 00:00:16,860 --> 00:00:19,620 So for example, you might have a component 6 00:00:19,620 --> 00:00:22,750 just has a few instance variables that are going to 7 00:00:23,677 --> 00:00:25,920 be data bound into the HTML. 8 00:00:25,920 --> 00:00:29,040 And in the HTML you might have a few buttons maybe, 9 00:00:29,040 --> 00:00:31,020 which when you click the button, 10 00:00:31,020 --> 00:00:33,450 it calls a function on your component 11 00:00:33,450 --> 00:00:36,930 which modifies the values of the data inside the component. 12 00:00:36,930 --> 00:00:39,300 So what you could do is you could actually 13 00:00:39,300 --> 00:00:42,240 test that component, just like a regular class. 14 00:00:42,240 --> 00:00:45,030 You could create an instance of the class manually. 15 00:00:45,030 --> 00:00:46,440 And then on that object, 16 00:00:46,440 --> 00:00:48,810 you can manually invoke its functions. 17 00:00:48,810 --> 00:00:51,030 You know, as if the user had clicked a button, 18 00:00:51,030 --> 00:00:52,350 well you can invoke the 19 00:00:52,350 --> 00:00:55,677 on click button manually to simplify matters, 20 00:00:55,677 --> 00:00:58,560 to simulate the user events. 21 00:00:58,560 --> 00:00:59,437 And then you can say, 22 00:00:59,437 --> 00:01:01,777 "Well, after I've called this function 23 00:01:01,777 --> 00:01:05,310 "has my data inside the object been changed?" 24 00:01:05,310 --> 00:01:06,960 So you can assert that the object state 25 00:01:06,960 --> 00:01:08,970 afterwards is correct. 26 00:01:08,970 --> 00:01:11,310 So you don't need the whole kind 27 00:01:11,310 --> 00:01:14,220 of angular framework to test this class. 28 00:01:14,220 --> 00:01:16,440 Just create a regular object, call its functions, 29 00:01:16,440 --> 00:01:20,160 and see what the data looks like afterwards. 30 00:01:20,160 --> 00:01:21,660 So we're gonna look at this approach first, 31 00:01:21,660 --> 00:01:23,670 a simple component that you can test 32 00:01:23,670 --> 00:01:25,800 just like a regular class. 33 00:01:25,800 --> 00:01:28,800 And then later on, we'll see how to do full testing 34 00:01:28,800 --> 00:01:31,410 when the situation gets more complex. 35 00:01:31,410 --> 00:01:32,310 Well, we have an example. 36 00:01:32,310 --> 00:01:36,000 If you're gonna do lesson 12, it's the first example. 37 00:01:36,000 --> 00:01:37,350 I've got a demo application. 38 00:01:37,350 --> 00:01:40,410 I created it using angular CLI, 39 00:01:40,410 --> 00:01:45,410 and I added a class called toggle switch component. 40 00:01:45,990 --> 00:01:47,370 It's a button. 41 00:01:47,370 --> 00:01:50,070 Every time you click it, it changes its state. 42 00:01:50,070 --> 00:01:52,656 Okay. So it goes, initially it's on. 43 00:01:52,656 --> 00:01:54,420 Then you click it, it's off. 44 00:01:54,420 --> 00:01:56,190 When you click it again, it goes on. 45 00:01:56,190 --> 00:01:57,720 When you click it again, it goes off. 46 00:01:57,720 --> 00:01:59,670 It toggles its state. 47 00:01:59,670 --> 00:02:02,400 So in my toggle switch component, 48 00:02:02,400 --> 00:02:04,684 actually, when it's created initially, 49 00:02:04,684 --> 00:02:09,290 it has an on is on state of false, okay? 50 00:02:09,290 --> 00:02:11,283 So the button is off at the moment. 51 00:02:12,360 --> 00:02:16,380 Imagine there's an HTML button that we can click. 52 00:02:16,380 --> 00:02:18,420 And here's my on click handler. 53 00:02:18,420 --> 00:02:20,940 When the user clicks a button on the webpage, 54 00:02:20,940 --> 00:02:24,600 it changes the property to be false or true. 55 00:02:24,600 --> 00:02:27,060 So every time the user clicks some kind 56 00:02:27,060 --> 00:02:28,500 of user interface button, 57 00:02:28,500 --> 00:02:33,500 it'll toggle the state of my component. 58 00:02:34,020 --> 00:02:36,140 I've got a property here called status. 59 00:02:36,140 --> 00:02:37,950 It's a string. 60 00:02:37,950 --> 00:02:42,390 It'll say the toggle switch is on or off. 61 00:02:42,390 --> 00:02:45,780 This is one of these JavaScript interpolated strings 62 00:02:45,780 --> 00:02:48,600 where you can have embedded expressions 63 00:02:48,600 --> 00:02:52,740 based on the value of my is on property. 64 00:02:52,740 --> 00:02:56,880 This status will either be the toggle switch is on 65 00:02:56,880 --> 00:02:59,117 or the toggle switch is off. 66 00:02:59,117 --> 00:03:02,670 When this component is rendered, 67 00:03:02,670 --> 00:03:05,250 it actually renders itself as HTML 68 00:03:05,250 --> 00:03:08,940 and the HTML has a button, okay? 69 00:03:08,940 --> 00:03:12,663 And that button basically has a click event. 70 00:03:13,650 --> 00:03:17,790 That click event, when you click this button in the UI, 71 00:03:17,790 --> 00:03:20,430 it'll call the click function up here 72 00:03:20,430 --> 00:03:22,920 to toggle the internal status. 73 00:03:22,920 --> 00:03:24,420 Whenever an event occurs, 74 00:03:24,420 --> 00:03:27,870 data binding is automatically re-executed. 75 00:03:27,870 --> 00:03:30,990 So if you change the flag here 76 00:03:30,990 --> 00:03:34,440 angular will automatically re-display the HTML. 77 00:03:34,440 --> 00:03:35,430 So from the top then, 78 00:03:35,430 --> 00:03:39,960 the HTML it says the status here is this function, okay? 79 00:03:39,960 --> 00:03:42,420 So this is a property. 80 00:03:42,420 --> 00:03:45,390 It'll call that function internally to get the status. 81 00:03:45,390 --> 00:03:48,820 Toggle switch is off will be initially displayed there 82 00:03:50,070 --> 00:03:52,623 and then a space and then a button. 83 00:03:53,580 --> 00:03:54,960 The button has a click event. 84 00:03:54,960 --> 00:03:57,030 This is how you handle events in angular. 85 00:03:57,030 --> 00:04:00,210 You put the name of the event into parenthesis 86 00:04:00,210 --> 00:04:04,620 and then you basically call your function in your component. 87 00:04:04,620 --> 00:04:06,330 So when the user clicks this button 88 00:04:06,330 --> 00:04:08,490 it'll invoke that function. 89 00:04:08,490 --> 00:04:11,370 That function toggles the is on flag. 90 00:04:11,370 --> 00:04:12,447 It'll be re-rendered. 91 00:04:12,447 --> 00:04:17,120 And by the way, the label of the button is displayed here. 92 00:04:17,120 --> 00:04:19,350 So we've got data binding here. 93 00:04:19,350 --> 00:04:21,690 We've got two bits of data binding really. 94 00:04:21,690 --> 00:04:23,850 Data binding to get the value 95 00:04:23,850 --> 00:04:26,924 of the status to be displayed there, 96 00:04:26,924 --> 00:04:31,260 and data binding to display the label of button, okay. 97 00:04:31,260 --> 00:04:32,910 Which is there. 98 00:04:32,910 --> 00:04:34,690 So the button is basically the opposite 99 00:04:34,690 --> 00:04:36,420 of the current state. 100 00:04:36,420 --> 00:04:38,730 If the toggle switch is off, 101 00:04:38,730 --> 00:04:42,603 then this button will say turn on. 102 00:04:43,440 --> 00:04:45,900 So if it's currently off the button will say 103 00:04:45,900 --> 00:04:48,420 click me to turn it on again. 104 00:04:48,420 --> 00:04:50,670 The state that you want to move into. 105 00:04:50,670 --> 00:04:53,160 So that's my toggle switch component. 106 00:04:53,160 --> 00:04:56,580 I render one of those in my application. 107 00:04:56,580 --> 00:04:58,320 So let me show you the code 108 00:04:58,320 --> 00:05:00,210 and then we'll look at the tests. 109 00:05:00,210 --> 00:05:03,840 So here's the code for my example one demo app. 110 00:05:03,840 --> 00:05:08,840 In my app folder we have a toggle switch component. 111 00:05:11,100 --> 00:05:12,750 We've also got a banner component, 112 00:05:12,750 --> 00:05:15,000 which we're gonna have a look at a bit later. 113 00:05:15,000 --> 00:05:17,670 My toggle switch component, it has this code. 114 00:05:17,670 --> 00:05:20,093 The code that we just looked at, 115 00:05:20,093 --> 00:05:25,093 it links in an HTML template, which is here, 116 00:05:26,970 --> 00:05:31,080 displays the status, toggle switch is currently off, 117 00:05:31,080 --> 00:05:32,850 handles the click event. 118 00:05:32,850 --> 00:05:36,303 And it displays a label on the button. 119 00:05:37,650 --> 00:05:38,910 I've got a star sheet. 120 00:05:38,910 --> 00:05:41,370 I could make it look beautiful if I wanted to. 121 00:05:41,370 --> 00:05:42,540 And I've got a spec, 122 00:05:42,540 --> 00:05:45,630 this is the unit test for my component. 123 00:05:45,630 --> 00:05:48,450 So that's obviously the focus of our attention. 124 00:05:48,450 --> 00:05:50,850 And we'll have a look at that in a moment. 125 00:05:50,850 --> 00:05:53,610 Just one other thing, in order to instantiate 126 00:05:53,610 --> 00:05:55,680 or to create one of those toggle switches, 127 00:05:55,680 --> 00:05:58,530 I forgot to mention my component 128 00:05:58,530 --> 00:06:02,250 has a selector app toggle switch. 129 00:06:02,250 --> 00:06:04,380 So if I wanted to create one of these toggle switches 130 00:06:04,380 --> 00:06:08,010 in my application, that's the selector that I use. 131 00:06:08,010 --> 00:06:09,930 And I've done that in my app component. 132 00:06:09,930 --> 00:06:13,860 My top level component app component in the HTML 133 00:06:13,860 --> 00:06:16,560 it basically creates an instance of the toggle switch. 134 00:06:18,604 --> 00:06:21,480 So if I show you here, 135 00:06:21,480 --> 00:06:23,523 this is what the application looks like. 136 00:06:24,360 --> 00:06:26,343 It's got quite a lot of bits going on. 137 00:06:27,692 --> 00:06:31,744 And in there it basically creates an instance 138 00:06:31,744 --> 00:06:33,750 of my toggle switch. 139 00:06:33,750 --> 00:06:35,790 So most all the stuff that's happening. 140 00:06:35,790 --> 00:06:38,310 This was actually the code generated by angular CLI 141 00:06:38,310 --> 00:06:42,300 which is crazy really, but here I've created an instance 142 00:06:42,300 --> 00:06:45,840 of my toggle switch component, plus this other 143 00:06:45,840 --> 00:06:48,750 banner component that we're gonna have a look at later. 144 00:06:48,750 --> 00:06:51,870 But for now that will create an instance 145 00:06:51,870 --> 00:06:54,060 of my toggle switch component. 146 00:06:54,060 --> 00:06:59,060 And that instance has this data and it has this HTML. 147 00:06:59,430 --> 00:07:01,710 So that's the HTML we should see when 148 00:07:01,710 --> 00:07:03,630 the application starts. 149 00:07:03,630 --> 00:07:05,760 So if you wanted to do this yourself, 150 00:07:05,760 --> 00:07:09,960 open a command window, in example one demo app. 151 00:07:09,960 --> 00:07:13,590 Do an NPM install to download the libraries, 152 00:07:13,590 --> 00:07:16,380 and then do an NG serve to actually 153 00:07:16,380 --> 00:07:19,500 build the application and serve it in a web server. 154 00:07:19,500 --> 00:07:23,130 And then open a browser, local host 4200. 155 00:07:23,130 --> 00:07:26,580 And you can see here, this is my toggle switch component. 156 00:07:26,580 --> 00:07:28,410 It has a status. 157 00:07:28,410 --> 00:07:30,420 The toggle switch is currently off, 158 00:07:30,420 --> 00:07:31,830 but I can turn it on. 159 00:07:31,830 --> 00:07:35,343 The status displays the current flag value. 160 00:07:40,116 --> 00:07:41,790 Actually I'll show the HTML first. 161 00:07:41,790 --> 00:07:45,570 The status is what we just saw. 162 00:07:45,570 --> 00:07:47,370 And the status says the toggle switch 163 00:07:47,370 --> 00:07:51,060 is off at the moment. 164 00:07:51,060 --> 00:07:54,270 And the button says click me to turn it on. 165 00:07:54,270 --> 00:07:58,113 So that button label is here. 166 00:07:59,100 --> 00:08:01,740 It's basically the opposite of the current state. 167 00:08:01,740 --> 00:08:04,950 So when I click that button, the click event occurs. 168 00:08:04,950 --> 00:08:08,880 It calls my click handler, changes the flag and then 169 00:08:08,880 --> 00:08:11,643 re-displays the toggle switch component. 170 00:08:13,033 --> 00:08:15,810 So it's currently on and I can turn it off. 171 00:08:15,810 --> 00:08:17,310 If I click it, it'll turn it off, 172 00:08:17,310 --> 00:08:19,080 and it's currently off. 173 00:08:19,080 --> 00:08:20,790 So every time you click it, 174 00:08:20,790 --> 00:08:25,790 the status and the labels switch, they toggle. 175 00:08:26,071 --> 00:08:28,740 So how can I test that component? 176 00:08:28,740 --> 00:08:31,050 Well, here's my spec. 177 00:08:31,050 --> 00:08:32,760 Here's the test. 178 00:08:32,760 --> 00:08:36,092 In toggle switch component spec ts. 179 00:08:36,092 --> 00:08:39,690 This here is just regular JavaScript 180 00:08:39,690 --> 00:08:42,360 and not using any angular specifics. 181 00:08:42,360 --> 00:08:45,360 This is just purely creating an instance of a class, 182 00:08:45,360 --> 00:08:49,113 call its functions, see the value of data afterwards. 183 00:08:50,160 --> 00:08:53,310 I've got a few tests here. 184 00:08:53,310 --> 00:08:56,610 Before each test, create a brand new instance 185 00:08:56,610 --> 00:08:58,020 of my toggle switch component 186 00:08:58,020 --> 00:09:01,260 which will be in the off state originally. 187 00:09:01,260 --> 00:09:02,970 So let's verify that. 188 00:09:02,970 --> 00:09:04,440 Let's verify that my toggle 189 00:09:04,440 --> 00:09:07,020 switch component is initially off. 190 00:09:07,020 --> 00:09:11,938 So in my component, it's got an is on flag that's public. 191 00:09:11,938 --> 00:09:14,583 I'm expecting it currently to be off. 192 00:09:15,570 --> 00:09:18,210 The status, the get status function 193 00:09:18,210 --> 00:09:21,420 effectively should be toggle switch is off. 194 00:09:21,420 --> 00:09:24,090 That's the status I expect to get back. 195 00:09:24,090 --> 00:09:27,540 The button label should be turn on. 196 00:09:27,540 --> 00:09:29,340 My component button label there, 197 00:09:29,340 --> 00:09:32,520 remember that was a property in my component. 198 00:09:32,520 --> 00:09:35,280 In my component, it had a button label property 199 00:09:35,280 --> 00:09:38,070 and basically check in that that button label 200 00:09:38,070 --> 00:09:41,040 property returned the correct value. 201 00:09:41,040 --> 00:09:44,373 Did my button label property return turn on? 202 00:09:45,300 --> 00:09:47,100 Okay, good. 203 00:09:47,100 --> 00:09:49,320 What about if we click the button? 204 00:09:49,320 --> 00:09:50,970 Well, when the button gets clicked 205 00:09:50,970 --> 00:09:54,090 in the real webpage, in the real component 206 00:09:54,090 --> 00:09:56,070 if this was actually run in a browser 207 00:09:56,070 --> 00:09:59,580 when the user clicks the button, it'll call this function. 208 00:09:59,580 --> 00:10:01,410 So what I can do is I can emulate that. 209 00:10:01,410 --> 00:10:04,270 I can just call that function directly in my test 210 00:10:05,460 --> 00:10:07,740 as if it was the user instigated action. 211 00:10:07,740 --> 00:10:10,020 But I can just call that function manually 212 00:10:10,020 --> 00:10:12,360 to simulate the click event 213 00:10:12,360 --> 00:10:15,960 and then see how my component reflects that change. 214 00:10:15,960 --> 00:10:18,690 So here, I'm going to take my component 215 00:10:18,690 --> 00:10:20,490 which has just been recreated. 216 00:10:20,490 --> 00:10:23,430 I'm going to simulate the user click in the button. 217 00:10:23,430 --> 00:10:25,410 In other words, I'm gonna call this function 218 00:10:25,410 --> 00:10:27,570 on my component manually. 219 00:10:27,570 --> 00:10:30,480 After that the component should have toggled. 220 00:10:30,480 --> 00:10:33,450 Its is on state should now be true. 221 00:10:33,450 --> 00:10:37,020 Its status should now be toggle switch is on, 222 00:10:37,020 --> 00:10:39,753 and the button label should now be turn off. 223 00:10:40,650 --> 00:10:42,960 So after one click, my component 224 00:10:42,960 --> 00:10:45,480 should now be in the on state. 225 00:10:45,480 --> 00:10:49,260 After two clicks it should revert back to the off state. 226 00:10:49,260 --> 00:10:51,750 Okay, well, I've actually got that test. 227 00:10:51,750 --> 00:10:53,760 If you go into the full code here, 228 00:10:53,760 --> 00:10:57,390 in my toggle switch component spec 229 00:10:57,390 --> 00:11:00,690 I've got this third function down here. 230 00:11:00,690 --> 00:11:04,773 Check that after two clicks, the component is off. 231 00:11:04,773 --> 00:11:07,590 Okay. So here we go. 232 00:11:07,590 --> 00:11:11,430 So I'm going to click once, click twice. 233 00:11:11,430 --> 00:11:13,860 After that I'm expecting my component to be back 234 00:11:13,860 --> 00:11:17,760 in the off state and its status should be off. 235 00:11:17,760 --> 00:11:19,590 The button should tell me I can turn it 236 00:11:19,590 --> 00:11:21,840 on by clicking the button. 237 00:11:21,840 --> 00:11:22,860 Okay. So there we go. 238 00:11:22,860 --> 00:11:25,110 So when you've got a simple component 239 00:11:25,110 --> 00:11:27,036 and the simple component has some simple state 240 00:11:27,036 --> 00:11:29,220 and some simple functions, 241 00:11:29,220 --> 00:11:30,960 the simplest way to test it 242 00:11:30,960 --> 00:11:33,750 would just be to call these functions directly 243 00:11:33,750 --> 00:11:35,970 from your test and then check the values 244 00:11:35,970 --> 00:11:37,770 of the properties afterwards to see 245 00:11:37,770 --> 00:11:39,930 if they've been updated correctly 246 00:11:39,930 --> 00:11:42,450 after the function has been evoked. 247 00:11:42,450 --> 00:11:43,623 Okay, we've done that. 248 00:11:45,756 --> 00:11:48,506 And we can see that those three tests are working fine.