1 00:00:06,721 --> 00:00:08,280 - In the previous section, 2 00:00:08,280 --> 00:00:12,840 we had a simple component with some data 3 00:00:12,840 --> 00:00:17,820 and it rendered a component HTML with a button. 4 00:00:17,820 --> 00:00:19,440 When the user clicked the button, 5 00:00:19,440 --> 00:00:22,740 it called an on click function in my component, 6 00:00:22,740 --> 00:00:26,580 updated the data, redisplayed itself in the webpage. 7 00:00:26,580 --> 00:00:28,800 In order to test that simple component, 8 00:00:28,800 --> 00:00:33,150 we didn't actually test real interaction with the webpage, 9 00:00:33,150 --> 00:00:35,550 we just simulated the event 10 00:00:35,550 --> 00:00:37,860 by calling the event handler directly. 11 00:00:37,860 --> 00:00:39,600 We basically said on our component, 12 00:00:39,600 --> 00:00:42,180 call the click handler directly 13 00:00:42,180 --> 00:00:44,700 as if the user had actually interacted 14 00:00:44,700 --> 00:00:45,903 with the real webpage. 15 00:00:46,740 --> 00:00:49,500 In full testing, you want to actually test 16 00:00:49,500 --> 00:00:52,380 that the event handler does actually work properly, okay? 17 00:00:52,380 --> 00:00:56,670 So in other words, you want to display the component 18 00:00:56,670 --> 00:00:59,640 or effectively render your component in your test suite 19 00:00:59,640 --> 00:01:04,590 and actually handle a real event from the button. 20 00:01:04,590 --> 00:01:08,250 Okay, so that it, then it calls your event handler properly. 21 00:01:08,250 --> 00:01:11,790 Your event handler updates the data in your component, 22 00:01:11,790 --> 00:01:15,510 redisplays the result in the webpage 23 00:01:15,510 --> 00:01:17,220 and then check the webpage to see 24 00:01:17,220 --> 00:01:19,110 if it's been updated properly. 25 00:01:19,110 --> 00:01:22,830 So in other words, this is full testing of the component. 26 00:01:22,830 --> 00:01:25,350 Does the component interact properly 27 00:01:25,350 --> 00:01:27,840 and fully with the DOM tree? 28 00:01:27,840 --> 00:01:29,700 Does it handle events properly? 29 00:01:29,700 --> 00:01:32,010 Does it update and redisplay content 30 00:01:32,010 --> 00:01:34,230 in the DOM tree afterwards? 31 00:01:34,230 --> 00:01:36,450 So in order to do this, 32 00:01:36,450 --> 00:01:38,460 you've actually gotta run your component 33 00:01:38,460 --> 00:01:41,880 in a kind of realistic environment 34 00:01:41,880 --> 00:01:45,060 used in full data binding with Angular. 35 00:01:45,060 --> 00:01:47,190 So we're gonna make use of a couple of classes 36 00:01:47,190 --> 00:01:48,870 we've already seen actually. 37 00:01:48,870 --> 00:01:53,507 TestBed, which enables us to kind of create the test model, 38 00:01:53,507 --> 00:01:57,960 the Angular test framework we'll know about our components, 39 00:01:57,960 --> 00:02:01,440 and then component fixture is like a wrapper 40 00:02:01,440 --> 00:02:03,000 on top of our component. 41 00:02:03,000 --> 00:02:05,370 It enables us to interact with the component 42 00:02:05,370 --> 00:02:07,380 from our test. 43 00:02:07,380 --> 00:02:10,680 So it's actually the same example 44 00:02:10,680 --> 00:02:12,690 as we looked at in the previous video. 45 00:02:12,690 --> 00:02:15,750 So in lesson 12, it's example one, 46 00:02:15,750 --> 00:02:18,060 the demo application in there. 47 00:02:18,060 --> 00:02:19,410 So here it is. 48 00:02:19,410 --> 00:02:21,930 And then in the previous video, 49 00:02:21,930 --> 00:02:25,290 we had a quick look at the toggle switch component. 50 00:02:25,290 --> 00:02:26,490 What we're gonna do now is have a look 51 00:02:26,490 --> 00:02:30,120 at the banner component instead, okay? 52 00:02:30,120 --> 00:02:31,950 It's still quite a simple component. 53 00:02:31,950 --> 00:02:34,680 It has some data which it displays, 54 00:02:34,680 --> 00:02:36,930 and we're gonna check with a button 55 00:02:36,930 --> 00:02:38,850 or with some event handlers. 56 00:02:38,850 --> 00:02:42,690 And when the user clicks and triggers events, 57 00:02:42,690 --> 00:02:46,620 we'll test that our code handles the events properly 58 00:02:46,620 --> 00:02:49,770 and updates itself properly in the webpage, okay? 59 00:02:49,770 --> 00:02:52,290 So here is the banner component. 60 00:02:52,290 --> 00:02:54,960 It displays a message and that message 61 00:02:54,960 --> 00:02:57,900 is in the title property and it's in Welsh. 62 00:02:57,900 --> 00:02:59,368 So how is your Welsh today? 63 00:02:59,368 --> 00:03:00,660 (speaking Welsh) 64 00:03:00,660 --> 00:03:01,610 Do you speak Welsh? 65 00:03:02,768 --> 00:03:05,160 Croeso pawb means welcome everybody. 66 00:03:05,160 --> 00:03:06,780 Welcome everybody. 67 00:03:06,780 --> 00:03:10,350 That's the title that my banner component is gonna display 68 00:03:10,350 --> 00:03:13,620 and it'll display it either up uppercase or lowercase 69 00:03:13,620 --> 00:03:15,963 based on this property. 70 00:03:16,830 --> 00:03:17,850 So what's gonna happen 71 00:03:17,850 --> 00:03:21,630 is initially it'll display that content, 72 00:03:21,630 --> 00:03:25,410 but when the user clicks on the content, 73 00:03:25,410 --> 00:03:27,480 I've got an on click handler 74 00:03:27,480 --> 00:03:29,640 which toggles the upper case flag. 75 00:03:29,640 --> 00:03:33,000 It makes it true instead of false or vice versa. 76 00:03:33,000 --> 00:03:35,670 And then depending on the new state, 77 00:03:35,670 --> 00:03:37,650 if we're now in uppercase mode, 78 00:03:37,650 --> 00:03:40,170 it sets the title to uppercase. 79 00:03:40,170 --> 00:03:43,226 Otherwise it sets the title to lowercase case. 80 00:03:43,226 --> 00:03:44,730 (indistinct) has a very simple example, 81 00:03:44,730 --> 00:03:48,720 some data and a handler to change that data. 82 00:03:48,720 --> 00:03:53,610 Remember, whenever an event occurs in Angular 83 00:03:53,610 --> 00:03:56,640 and a component event handler is fired, 84 00:03:56,640 --> 00:03:59,370 Angular will call this event handler 85 00:03:59,370 --> 00:04:02,640 and it'll automatically rebind in a webpage, 86 00:04:02,640 --> 00:04:06,450 it'll automatically rebind and redisplay the HTML. 87 00:04:06,450 --> 00:04:09,810 So the HTML for my banner component looks like this. 88 00:04:09,810 --> 00:04:12,480 Is a really simple component. 89 00:04:12,480 --> 00:04:15,570 It has a heading which displays the title. 90 00:04:15,570 --> 00:04:18,030 So there's a bit of data binding there. 91 00:04:18,030 --> 00:04:21,060 That title is that title up there. 92 00:04:21,060 --> 00:04:23,760 Curly brackets, double curly brackets. 93 00:04:23,760 --> 00:04:25,710 When my H1 click event occurs, 94 00:04:25,710 --> 00:04:30,600 remember in Angular, you put events in parenthesis. 95 00:04:30,600 --> 00:04:33,000 When somebody clicks on that H1, 96 00:04:33,000 --> 00:04:36,300 it'll invoke this function up here, okay? 97 00:04:36,300 --> 00:04:38,013 Which will change the title, 98 00:04:39,150 --> 00:04:41,040 which will cause it to be redisplayed 99 00:04:41,040 --> 00:04:43,170 automatically in the page. 100 00:04:43,170 --> 00:04:46,620 So let's actually run it first of all, to see how it works. 101 00:04:46,620 --> 00:04:48,540 If you wanna run this application, 102 00:04:48,540 --> 00:04:53,520 go into lesson 12, example one, demo app, 103 00:04:53,520 --> 00:04:56,760 open up a command window, do an NPM install 104 00:04:56,760 --> 00:05:00,690 to install the libraries and then do an NG serve 105 00:05:00,690 --> 00:05:02,880 to run the web server 106 00:05:02,880 --> 00:05:07,380 and then open a browser, go to local host 4200. 107 00:05:07,380 --> 00:05:09,640 And here it is. 108 00:05:09,640 --> 00:05:10,680 Here, well, first of all, 109 00:05:10,680 --> 00:05:13,650 there's the toggle switch that we looked at before. 110 00:05:13,650 --> 00:05:17,520 Here is my banner component, croeso pawb, 111 00:05:17,520 --> 00:05:18,840 welcome everybody. 112 00:05:18,840 --> 00:05:23,580 If I click on it, the click event was handled. 113 00:05:23,580 --> 00:05:25,630 It set the flag to be uppercase 114 00:05:26,730 --> 00:05:29,430 and then it changed the title to be uppercase. 115 00:05:29,430 --> 00:05:32,580 And then it automatically refreshed itself in the browser. 116 00:05:32,580 --> 00:05:34,243 If I click again, it goes lowercase. 117 00:05:34,243 --> 00:05:37,530 If I click again, it goes uppercase. 118 00:05:37,530 --> 00:05:38,363 All right? 119 00:05:38,363 --> 00:05:39,600 So it is actually working. 120 00:05:39,600 --> 00:05:41,950 And well, obviously this banner component 121 00:05:43,290 --> 00:05:46,233 is being rendered as part of my main application. 122 00:05:47,130 --> 00:05:48,930 So I guess we should look at that as well, shouldn't we? 123 00:05:48,930 --> 00:05:53,930 In my banner component, it's selector is at banner. 124 00:05:54,540 --> 00:05:57,390 So if I wanna create it, 125 00:05:57,390 --> 00:05:59,580 that's the element name that I need. 126 00:05:59,580 --> 00:06:02,430 In my application component, app component, 127 00:06:02,430 --> 00:06:04,410 my route component. 128 00:06:04,410 --> 00:06:08,490 If you scroll down to line 354, would you believe? 129 00:06:08,490 --> 00:06:11,370 There it displays the app component banner. 130 00:06:11,370 --> 00:06:15,780 Each app banner, if I had several of these, 131 00:06:15,780 --> 00:06:17,820 each one would be a different object. 132 00:06:17,820 --> 00:06:19,260 Each one would be a different object 133 00:06:19,260 --> 00:06:21,090 with its own internal state, okay? 134 00:06:21,090 --> 00:06:24,330 It's just like having one instance of a bank account, 135 00:06:24,330 --> 00:06:26,010 another instance of a bank account, 136 00:06:26,010 --> 00:06:29,160 and another instance, they've each got their own values. 137 00:06:29,160 --> 00:06:30,540 So I've got three banners now, 138 00:06:30,540 --> 00:06:33,900 each has its own state and its own event handler. 139 00:06:33,900 --> 00:06:36,180 I can click on any one of them, okay. 140 00:06:36,180 --> 00:06:37,320 If I click on that one, 141 00:06:37,320 --> 00:06:39,930 then just that one goes into uppercase. 142 00:06:39,930 --> 00:06:42,184 If I click on that one and that one, okay? 143 00:06:42,184 --> 00:06:44,250 So you can see, basically each component 144 00:06:44,250 --> 00:06:47,700 has its own individual state and it knows what's going on. 145 00:06:47,700 --> 00:06:48,810 That makes sense. 146 00:06:48,810 --> 00:06:51,510 So I wanna test that now in my code. 147 00:06:51,510 --> 00:06:53,280 So I'm gonna go into my banner component 148 00:06:53,280 --> 00:06:54,810 and write some test code. 149 00:06:54,810 --> 00:06:57,540 So in my banner folder, remember each component 150 00:06:57,540 --> 00:06:59,973 goes into a separate folder in Angular. 151 00:07:00,810 --> 00:07:03,690 So we have our banner component spec. 152 00:07:03,690 --> 00:07:08,160 So in here, we're going to test what happens 153 00:07:08,160 --> 00:07:10,530 when you click the initially what state 154 00:07:10,530 --> 00:07:12,300 is my banner component in? 155 00:07:12,300 --> 00:07:14,670 And then what happens when I click it once, 156 00:07:14,670 --> 00:07:16,410 twice, three times. 157 00:07:16,410 --> 00:07:19,083 So let's see what's going on here. 158 00:07:21,150 --> 00:07:21,983 Right then. 159 00:07:21,983 --> 00:07:24,633 So, first of all, here's my banner component spec. 160 00:07:25,560 --> 00:07:28,590 You need to set up a test model 161 00:07:28,590 --> 00:07:30,390 that knows about your component. 162 00:07:30,390 --> 00:07:34,470 Set up a test module that knows about my banner component. 163 00:07:34,470 --> 00:07:38,070 And that banner component has an HDML template. 164 00:07:38,070 --> 00:07:42,570 That HDML template has to be compiled into pure JavaScript. 165 00:07:42,570 --> 00:07:44,220 Okay, this is what happens when you normally 166 00:07:44,220 --> 00:07:45,570 build an application. 167 00:07:45,570 --> 00:07:47,313 In our test environment here, 168 00:07:50,581 --> 00:07:53,310 load the banner component into the test module, 169 00:07:53,310 --> 00:07:56,250 compile the HTML into JavaScript. 170 00:07:56,250 --> 00:08:01,250 So my TestBed now knows about the banner component, okay? 171 00:08:01,590 --> 00:08:06,590 So before each test, 172 00:08:07,350 --> 00:08:10,860 we can ask the TestBed to create a new instance 173 00:08:10,860 --> 00:08:12,780 of the banner component. 174 00:08:12,780 --> 00:08:15,270 Fixture is a wrapper, remember. 175 00:08:15,270 --> 00:08:17,490 Whenever you say create component, 176 00:08:17,490 --> 00:08:18,810 it does create the component 177 00:08:18,810 --> 00:08:20,810 but what it gives you back is a fixture. 178 00:08:23,490 --> 00:08:27,120 That's the fixture available, okay. 179 00:08:27,120 --> 00:08:28,230 Fixture. 180 00:08:28,230 --> 00:08:31,200 And that fixture is a wrapper for the component. 181 00:08:31,200 --> 00:08:33,960 It has a property component instance 182 00:08:33,960 --> 00:08:38,960 and that actually is the component of interest, like that. 183 00:08:39,240 --> 00:08:40,073 Okay? 184 00:08:40,073 --> 00:08:41,910 So that's the component variable there. 185 00:08:41,910 --> 00:08:45,360 The component variable is the actual component 186 00:08:45,360 --> 00:08:46,920 that's been rendered. 187 00:08:46,920 --> 00:08:49,440 So that component there will have some data, 188 00:08:49,440 --> 00:08:51,690 it'll have data in there. 189 00:08:51,690 --> 00:08:55,260 And remember what happens when you say detect changes? 190 00:08:55,260 --> 00:08:57,210 When you call the detect changes function 191 00:08:57,210 --> 00:08:59,610 basically it means do data binding. 192 00:08:59,610 --> 00:09:02,220 From the fixture, go to the component, 193 00:09:02,220 --> 00:09:06,930 whatever data is in here, basically update the HTML template 194 00:09:06,930 --> 00:09:10,533 rebind the data in the component into the HTML. 195 00:09:11,370 --> 00:09:12,990 That's what detect changes means. 196 00:09:12,990 --> 00:09:17,760 Do data binding on the HTML, right. 197 00:09:17,760 --> 00:09:20,400 So that's gonna happen before each test. 198 00:09:20,400 --> 00:09:22,800 It's gonna basically set up a component 199 00:09:22,800 --> 00:09:24,120 in pristine condition. 200 00:09:24,120 --> 00:09:28,260 So initially the banner will be lowercase, croeso pawb! 201 00:09:28,260 --> 00:09:31,140 Right, now here's a test. 202 00:09:31,140 --> 00:09:33,443 Initially the heading should display this test, 203 00:09:33,443 --> 00:09:36,000 "croeso pawb!" 204 00:09:36,000 --> 00:09:36,833 Right. 205 00:09:36,833 --> 00:09:40,110 So I need to remind you again, what's going on. 206 00:09:40,110 --> 00:09:44,790 The fixture is a wrapper to the component 207 00:09:44,790 --> 00:09:48,930 and the component has some HTML, okay? 208 00:09:48,930 --> 00:09:51,990 And that HTML will be rendered. 209 00:09:51,990 --> 00:09:55,920 When you say this fixture DOM native element, 210 00:09:55,920 --> 00:09:57,480 what you're basically doing is you're saying, 211 00:09:57,480 --> 00:09:59,940 okay, so this component here, 212 00:09:59,940 --> 00:10:03,453 ultimately that component is gonna render a chunk of HTML. 213 00:10:05,774 --> 00:10:06,960 A heading one or something. 214 00:10:06,960 --> 00:10:10,980 This will give you back a reference to the HTML 215 00:10:10,980 --> 00:10:13,500 that's actually been rendered by the component 216 00:10:13,500 --> 00:10:15,810 because obviously that's what we want to test. 217 00:10:15,810 --> 00:10:18,900 Give me back the actual HTML rendered 218 00:10:18,900 --> 00:10:21,360 by the component as an HTML element. 219 00:10:21,360 --> 00:10:25,290 This is just to keep the type script compiler happy, okay. 220 00:10:25,290 --> 00:10:27,093 So this banner element here, 221 00:10:28,860 --> 00:10:31,770 inside there there should be an H1 222 00:10:31,770 --> 00:10:34,320 because my banner component renders H1. 223 00:10:34,320 --> 00:10:37,533 Grab the H1 inside my banner component. 224 00:10:38,520 --> 00:10:41,580 And that H1, it could be null, 225 00:10:41,580 --> 00:10:42,990 so we have to be a bit careful, 226 00:10:42,990 --> 00:10:45,210 the safe navigation operator. 227 00:10:45,210 --> 00:10:49,770 If H1 isn't null, grab the text content for the heading, 228 00:10:49,770 --> 00:10:52,553 it should be "croeso pawb!" 229 00:10:54,644 --> 00:10:55,477 Here it is. 230 00:10:57,240 --> 00:11:00,570 So grab the HTML rendered for the component. 231 00:11:00,570 --> 00:11:02,610 In there there should be an H1. 232 00:11:02,610 --> 00:11:04,680 Get the text content for the H1, 233 00:11:04,680 --> 00:11:07,540 verify that it says croeso pawb! 234 00:11:07,540 --> 00:11:10,860 Okay, so basically that was the text there, 235 00:11:10,860 --> 00:11:15,300 but the HTML, the H1, there should be an H1 236 00:11:15,300 --> 00:11:17,390 with text content that says croeso pawb! 237 00:11:17,390 --> 00:11:19,263 That's what it should be. 238 00:11:21,330 --> 00:11:23,040 Okay, so there we go. 239 00:11:23,040 --> 00:11:25,833 Let's just run through the steps we've just done. 240 00:11:27,810 --> 00:11:29,400 Great. 241 00:11:29,400 --> 00:11:31,980 What about if the user clicked the button? 242 00:11:31,980 --> 00:11:34,620 Well, this is how you simulate button events. 243 00:11:34,620 --> 00:11:36,600 There's a new thing we haven't seen yet. 244 00:11:36,600 --> 00:11:41,160 So from the top, grab the HTML that's been rendered. 245 00:11:41,160 --> 00:11:43,530 So again, we had the fixed your object. 246 00:11:43,530 --> 00:11:46,560 The fixed your object pointed to the component. 247 00:11:46,560 --> 00:11:50,880 The component had an HTML template associated with it 248 00:11:50,880 --> 00:11:55,410 which will render a certain chunk of HTML, 249 00:11:55,410 --> 00:11:59,550 basically an H1 which I can click on. 250 00:11:59,550 --> 00:12:02,730 So grab the H1 from this HTML. 251 00:12:02,730 --> 00:12:06,000 So in here, grab the H1 from in there, 252 00:12:06,000 --> 00:12:08,700 and on that H1, dispatch event. 253 00:12:08,700 --> 00:12:12,240 Okay, so this is basically how you simulate events 254 00:12:12,240 --> 00:12:13,170 using Jasmine. 255 00:12:13,170 --> 00:12:16,950 You say, take the element and dispatch this event. 256 00:12:16,950 --> 00:12:20,070 You create an event object and the name of the event. 257 00:12:20,070 --> 00:12:24,410 It's basically simulating a click event on the H1, okay. 258 00:12:24,410 --> 00:12:28,560 So if the user did click on the H1, 259 00:12:28,560 --> 00:12:32,973 it should have called the on click handler in my component. 260 00:12:34,320 --> 00:12:36,720 Okay and that click handler will have changed 261 00:12:36,720 --> 00:12:39,270 the values in here, okay. 262 00:12:39,270 --> 00:12:43,890 It'll have changed the value of the title to be upper case. 263 00:12:43,890 --> 00:12:47,520 The thing is it doesn't automatically rerender. 264 00:12:47,520 --> 00:12:49,800 When you're testing, it doesn't automatically 265 00:12:49,800 --> 00:12:51,030 do data binding. 266 00:12:51,030 --> 00:12:53,820 So even though, when we click the button 267 00:12:53,820 --> 00:12:55,260 or when we click the head in, 268 00:12:55,260 --> 00:12:57,150 it'll call the event handler, 269 00:12:57,150 --> 00:13:00,030 the data inside my component will have changed 270 00:13:00,030 --> 00:13:03,330 but it doesn't automatically refresh the HTML, 271 00:13:03,330 --> 00:13:06,510 not in your test, it does doesn't. 272 00:13:06,510 --> 00:13:08,910 In the regular angle application 273 00:13:08,910 --> 00:13:10,290 when the event handler occurs, 274 00:13:10,290 --> 00:13:13,110 it'll automatically reexecute data binding 275 00:13:13,110 --> 00:13:17,040 to refresh the webpage but it doesn't do that automatically 276 00:13:17,040 --> 00:13:18,930 in your test environment. 277 00:13:18,930 --> 00:13:21,120 So even though we've clicked the event, 278 00:13:21,120 --> 00:13:24,180 to dispatch the click event to H1, 279 00:13:24,180 --> 00:13:27,390 we have to forcibly rebind, okay? 280 00:13:27,390 --> 00:13:28,620 Always remember to do this. 281 00:13:28,620 --> 00:13:30,180 This is what I forget. 282 00:13:30,180 --> 00:13:34,318 When you change the data in the component in the test, 283 00:13:34,318 --> 00:13:35,700 you have to detect changes. 284 00:13:35,700 --> 00:13:39,810 The fixture basically detects the changes of the data 285 00:13:39,810 --> 00:13:43,020 and it updates the rendered HTML. 286 00:13:43,020 --> 00:13:44,970 So the HTML is now updated 287 00:13:44,970 --> 00:13:49,800 and now the HTML should be in uppercase, CROESO PAWB! 288 00:13:49,800 --> 00:13:53,793 So if I'd forgotten to do a detect changes, 289 00:13:55,320 --> 00:13:57,210 the HTML wouldn't have changed. 290 00:13:57,210 --> 00:14:00,540 The data inside my component would've changed, 291 00:14:00,540 --> 00:14:02,460 but the HTML would not have been updated. 292 00:14:02,460 --> 00:14:05,310 So remember to do this. 293 00:14:05,310 --> 00:14:07,140 Whenever you change the component, 294 00:14:07,140 --> 00:14:10,353 remember this statement here, really important. 295 00:14:11,820 --> 00:14:13,950 Okay, so that's great. 296 00:14:13,950 --> 00:14:16,110 So what we can do now is we can just run the tests. 297 00:14:16,110 --> 00:14:18,150 So you could open up another command window 298 00:14:18,150 --> 00:14:20,100 and then just do an NG test. 299 00:14:20,100 --> 00:14:21,363 You can do this. 300 00:14:23,487 --> 00:14:25,680 If your application contains lots of tests, 301 00:14:25,680 --> 00:14:28,590 you can just tell it to run just one test file. 302 00:14:28,590 --> 00:14:30,540 If you like, you say, entry test, 303 00:14:30,540 --> 00:14:33,840 and then you say which test files to include. 304 00:14:33,840 --> 00:14:37,080 The ** means like any sub directory. 305 00:14:37,080 --> 00:14:41,100 In any subdirectory find the banner component spec 306 00:14:41,100 --> 00:14:42,960 and only run that test 307 00:14:42,960 --> 00:14:45,060 because you've probably got lots of components 308 00:14:45,060 --> 00:14:47,220 and I just want to test this component, okay? 309 00:14:47,220 --> 00:14:48,360 Is it gonna work? 310 00:14:48,360 --> 00:14:49,620 Yes, it does. 311 00:14:49,620 --> 00:14:54,620 So initially it displayed "croeso pawb!, 312 00:14:54,780 --> 00:14:59,610 after one click event, it contained the text in uppercase. 313 00:14:59,610 --> 00:15:01,140 I've also got another function. 314 00:15:01,140 --> 00:15:02,850 You can have a look at the code if you like 315 00:15:02,850 --> 00:15:05,010 to simulate two click events 316 00:15:05,010 --> 00:15:06,270 in which case it should have revert it 317 00:15:06,270 --> 00:15:09,450 back to lowercase again, okay? 318 00:15:09,450 --> 00:15:10,283 So there we go. 319 00:15:10,283 --> 00:15:12,690 That's a realistic example that we've just seen 320 00:15:12,690 --> 00:15:17,100 of how to create the component, how to dispatch events 321 00:15:17,100 --> 00:15:20,730 to cause your call back which will update the data. 322 00:15:20,730 --> 00:15:23,700 Remember to say fixture detect changes 323 00:15:23,700 --> 00:15:27,693 to rebind the HTML so that it's been updated properly.