1 00:00:06,555 --> 00:00:08,190 - In this section, we're going to write 2 00:00:08,190 --> 00:00:10,680 some real JavaScript tests 3 00:00:10,680 --> 00:00:13,860 that execute against real JavaScript code 4 00:00:13,860 --> 00:00:15,900 that talks to a real HTML document. 5 00:00:15,900 --> 00:00:17,970 So, this is the, the correct way 6 00:00:17,970 --> 00:00:21,480 to test JavaScript talking to an actual webpage. 7 00:00:21,480 --> 00:00:25,950 So, it's in this folder: JsDom_LoadingHtmlAndJs. 8 00:00:25,950 --> 00:00:27,390 Let's take a quick look there first, 9 00:00:27,390 --> 00:00:29,220 before we look at the details. 10 00:00:29,220 --> 00:00:30,840 So, there's the folder 11 00:00:30,840 --> 00:00:35,790 in Lesson 8, at JsDom_LoadingHtmlAndJs. 12 00:00:35,790 --> 00:00:37,800 If you open that in a code editor, 13 00:00:37,800 --> 00:00:40,500 what you'll find is a couple of things actually, 14 00:00:40,500 --> 00:00:41,790 well quite a few things. 15 00:00:41,790 --> 00:00:43,440 I've got the HTML document. 16 00:00:43,440 --> 00:00:46,170 that's going to be loaded into my test. 17 00:00:46,170 --> 00:00:49,230 I've got the code, which I want to test. 18 00:00:49,230 --> 00:00:52,590 This is my actual code, my script. 19 00:00:52,590 --> 00:00:55,260 That's some real JavaScript that I want to test. 20 00:00:55,260 --> 00:00:57,870 I'll go to that in a moment. 21 00:00:57,870 --> 00:00:59,370 But the tests are written here 22 00:01:00,780 --> 00:01:02,850 and then I've got a bit of configuration 23 00:01:02,850 --> 00:01:03,840 that I need to explain. 24 00:01:03,840 --> 00:01:08,370 I've got configuration defined in my package.json 25 00:01:08,370 --> 00:01:10,650 that I need to just explain. 26 00:01:10,650 --> 00:01:12,720 And I've also got some configuration 27 00:01:12,720 --> 00:01:16,410 in jest.config that I'm just going to confirm. 28 00:01:16,410 --> 00:01:19,500 And I've got some other configuration in babel.config. 29 00:01:19,500 --> 00:01:23,010 Okay. So, three different configuration files, 30 00:01:23,010 --> 00:01:25,410 effectively, that I need to describe, 31 00:01:25,410 --> 00:01:28,350 plus the HTML page, 32 00:01:28,350 --> 00:01:31,500 the code that accesses the HTML page, 33 00:01:31,500 --> 00:01:33,870 and the test against that code. 34 00:01:33,870 --> 00:01:35,130 Okay. So, there were few things 35 00:01:35,130 --> 00:01:36,720 that we need to discuss first. 36 00:01:36,720 --> 00:01:38,520 So, I think the first place 37 00:01:38,520 --> 00:01:41,010 is just to have a look at the HTML document 38 00:01:41,010 --> 00:01:43,290 and I'll explain the scenario. 39 00:01:43,290 --> 00:01:46,292 So, the idea is this is a table of products. 40 00:01:46,292 --> 00:01:49,560 It's got three rows for three different products. 41 00:01:49,560 --> 00:01:51,420 Each row has got two columns. 42 00:01:51,420 --> 00:01:54,098 So, for example, the first row: 43 00:01:54,098 --> 00:01:57,780 in the first column is the name of the product, 44 00:01:57,780 --> 00:01:59,970 in the second column is the price. 45 00:01:59,970 --> 00:02:04,230 I'm using CSS classes to differentiate between the columns. 46 00:02:04,230 --> 00:02:07,410 The first column has a description class, 47 00:02:07,410 --> 00:02:09,630 description, description, 48 00:02:09,630 --> 00:02:12,300 and then for each row the second column 49 00:02:12,300 --> 00:02:16,230 has a CSS class of price, price, and price. 50 00:02:16,230 --> 00:02:18,450 So, what I'm actually gonna do in my code, 51 00:02:18,450 --> 00:02:22,560 is I'm gonna find all the, all the table definition cells, 52 00:02:22,560 --> 00:02:25,140 all the table data that have a class, 53 00:02:25,140 --> 00:02:27,360 a CSS class of price. 54 00:02:27,360 --> 00:02:29,340 I'm gonna grab these values 55 00:02:29,340 --> 00:02:31,560 and I'm gonna add them up in my code 56 00:02:31,560 --> 00:02:33,300 and give out the total. 57 00:02:33,300 --> 00:02:34,950 And then I'm gonna write a test 58 00:02:34,950 --> 00:02:37,770 to make sure that the total is correct. 59 00:02:37,770 --> 00:02:39,630 So, that's the HTML content. 60 00:02:39,630 --> 00:02:40,590 Just looking at this, 61 00:02:40,590 --> 00:02:42,810 there's my TD with a class price, 62 00:02:42,810 --> 00:02:44,940 another TD with a class price, 63 00:02:44,940 --> 00:02:47,520 and then the third TD with a class price. 64 00:02:47,520 --> 00:02:48,690 So, the next step: 65 00:02:48,690 --> 00:02:53,070 let's write some code to actually calculate the total price. 66 00:02:53,070 --> 00:02:55,890 So, here it is: myscript.js. 67 00:02:55,890 --> 00:02:57,810 That's in the code folder as well 68 00:02:57,810 --> 00:03:00,000 if you want to just have a look at it. 69 00:03:00,000 --> 00:03:01,020 So, let's have a look at it. 70 00:03:01,020 --> 00:03:04,710 It's, first of all, it's exported. 71 00:03:04,710 --> 00:03:06,990 It calculates the total price. 72 00:03:06,990 --> 00:03:08,850 So it goes to the document, 73 00:03:08,850 --> 00:03:10,380 it searches. 74 00:03:10,380 --> 00:03:13,410 First of all, it gets the products table. 75 00:03:13,410 --> 00:03:15,750 Products table is the table that contains 76 00:03:15,750 --> 00:03:17,940 all the table cells. 77 00:03:17,940 --> 00:03:21,810 Within that table, I select all elements 78 00:03:21,810 --> 00:03:25,830 that have a TD element name and a price class. 79 00:03:25,830 --> 00:03:29,430 So, this syntax: search for the element name TD 80 00:03:29,430 --> 00:03:32,400 and the .price is a class. 81 00:03:32,400 --> 00:03:37,020 It'll gimme back all the TD elements for the prices. 82 00:03:37,020 --> 00:03:40,650 So, it'll basically select the three price elements. 83 00:03:40,650 --> 00:03:42,540 I'm gonna add those values up together. 84 00:03:42,540 --> 00:03:44,550 So, set the total to zero, 85 00:03:44,550 --> 00:03:47,430 loop through all the price elements, 86 00:03:47,430 --> 00:03:50,340 the three TD price elements. 87 00:03:50,340 --> 00:03:53,880 For each TD element, get the inner HTML. 88 00:03:53,880 --> 00:03:56,280 And that would be a number, like 300. 89 00:03:56,280 --> 00:03:58,140 But when you get text from a webpage, 90 00:03:58,140 --> 00:04:00,090 it always comes back as a string. 91 00:04:00,090 --> 00:04:02,490 So, I need to convert it into number. 92 00:04:02,490 --> 00:04:05,130 And once I've got the number, I can add it to the total. 93 00:04:05,130 --> 00:04:06,900 And at the end, I return the total. 94 00:04:06,900 --> 00:04:08,970 So, that should hopefully work. 95 00:04:08,970 --> 00:04:10,380 If this code is correct, 96 00:04:10,380 --> 00:04:12,870 it should give me back the correct number 97 00:04:12,870 --> 00:04:15,033 when I feed it that HTML document. 98 00:04:16,170 --> 00:04:18,720 Okay. Now, just one observation. 99 00:04:18,720 --> 00:04:21,930 This here is an ECMAScript module. 100 00:04:21,930 --> 00:04:25,920 There are two main types of module or file in JavaScript. 101 00:04:25,920 --> 00:04:27,090 We have 102 00:04:27,090 --> 00:04:29,490 what we've been looking at most of this video series 103 00:04:29,490 --> 00:04:32,970 is common Js modules, 104 00:04:32,970 --> 00:04:35,490 which kinda like node.js, 105 00:04:35,490 --> 00:04:37,890 where in a common Js module, 106 00:04:37,890 --> 00:04:39,360 at the end of the module, 107 00:04:39,360 --> 00:04:42,210 you'd have a statement like module.exports 108 00:04:42,210 --> 00:04:46,470 to say which symbols are exported can be imported elsewhere. 109 00:04:46,470 --> 00:04:50,550 But in a web browser, we don't use common Js. 110 00:04:50,550 --> 00:04:52,020 We use ECMAScript module. 111 00:04:52,020 --> 00:04:54,873 We use this syntax for exporting symbols. 112 00:04:55,740 --> 00:04:56,640 Okay. 113 00:04:56,640 --> 00:05:01,640 So, the way in order to support ECMAScript modules in Jest, 114 00:05:03,180 --> 00:05:05,550 we have to have a bit of configuration 115 00:05:05,550 --> 00:05:10,230 so that it knows to expect this ECMAScript module syntax, 116 00:05:10,230 --> 00:05:14,340 instead of supporting the common Js module syntax. 117 00:05:14,340 --> 00:05:19,320 So, to summarize, to enable us to use ECMAScript modules 118 00:05:19,320 --> 00:05:24,320 in our tests, we have to configure our environment. 119 00:05:24,570 --> 00:05:28,050 In order to allow ECMAScript modules to be loaded by Jest, 120 00:05:28,050 --> 00:05:31,380 we've gotta tell it to use Babel, basically. 121 00:05:31,380 --> 00:05:33,120 In my package.json, 122 00:05:33,120 --> 00:05:35,973 I've added some development dependencies for Babel. 123 00:05:36,990 --> 00:05:37,823 Okay. 124 00:05:37,823 --> 00:05:41,430 And you have to then install those packages in your folder. 125 00:05:41,430 --> 00:05:44,160 Okay. So, if you wanna run these tests yourself, 126 00:05:44,160 --> 00:05:45,160 go to the folder 127 00:05:47,010 --> 00:05:48,160 JsDom_LoadingHtmlAndJs, 128 00:05:50,220 --> 00:05:52,380 open a command prompt window, 129 00:05:52,380 --> 00:05:56,010 and in that command prompt window, type in this command: 130 00:05:56,010 --> 00:05:58,800 npm install, 131 00:05:58,800 --> 00:06:00,360 or yarn install, 132 00:06:00,360 --> 00:06:02,940 and that will install the Babel packages. 133 00:06:02,940 --> 00:06:03,960 It takes a moment or two- 134 00:06:03,960 --> 00:06:06,720 probably takes about 30 seconds to install those. 135 00:06:06,720 --> 00:06:10,320 Okay. So, assume that you've done that on your machine. 136 00:06:10,320 --> 00:06:13,830 Once you've done that, you can then run the tests. 137 00:06:13,830 --> 00:06:17,160 Okay. So, I'll leave that go assuming that's gonna work. 138 00:06:17,160 --> 00:06:19,410 There is another piece of configuration. 139 00:06:19,410 --> 00:06:24,000 You've also kind of gotta configure the Babel transpilar. 140 00:06:24,000 --> 00:06:25,320 Babel is a transpilar 141 00:06:25,320 --> 00:06:28,950 that converts modern ECMAScript syntax 142 00:06:28,950 --> 00:06:30,720 into traditional JavaScript. 143 00:06:30,720 --> 00:06:33,810 Okay. So, in my, I've got another file 144 00:06:33,810 --> 00:06:38,013 called babel.config.json, which is here. 145 00:06:39,540 --> 00:06:42,090 And in there, basically the Babel preset that 146 00:06:42,090 --> 00:06:43,780 this is quite a complicated area. 147 00:06:43,780 --> 00:06:45,450 The way that Babel works: 148 00:06:45,450 --> 00:06:48,570 there are a thing called presets that basically tell Babel 149 00:06:48,570 --> 00:06:51,750 what kind of conversions is it meant to do. 150 00:06:51,750 --> 00:06:53,730 And when you set this preset, 151 00:06:53,730 --> 00:06:57,053 basically what that says is 152 00:06:57,053 --> 00:06:59,190 I'm going to, I want be able to 153 00:06:59,190 --> 00:07:02,970 transpile my code into ECMAScript 2015. 154 00:07:02,970 --> 00:07:06,420 This is the baseline version of traditional JavaScript. 155 00:07:06,420 --> 00:07:08,580 It's the lowest common denominator, 156 00:07:08,580 --> 00:07:12,300 all browsers support at least ECMAScript 2015. 157 00:07:12,300 --> 00:07:15,633 Okay. So, that's also necessary. 158 00:07:17,430 --> 00:07:20,430 Okay. So, now then, here is my test. 159 00:07:20,430 --> 00:07:22,020 Now there's, there are a couple of things 160 00:07:22,020 --> 00:07:25,560 that I need to point out here. 161 00:07:25,560 --> 00:07:27,600 We've got two separate files involved: 162 00:07:27,600 --> 00:07:30,180 an HTML file and code. 163 00:07:30,180 --> 00:07:32,760 We need to load them both into our test 164 00:07:32,760 --> 00:07:34,260 before we can run the test. 165 00:07:34,260 --> 00:07:36,840 So, let me give you a quick sketch. 166 00:07:36,840 --> 00:07:40,350 So, first of all, we had the HTML file. 167 00:07:40,350 --> 00:07:42,930 Okay. That contains the actual data, 168 00:07:42,930 --> 00:07:46,589 if you like, or the HTML content indexed on HTML. 169 00:07:46,589 --> 00:07:51,589 This statement will load that HTML into my test. 170 00:07:52,587 --> 00:07:54,843 So, if I draw my test kind of here, 171 00:07:57,420 --> 00:08:01,560 this bit of code here will load the HTML document 172 00:08:01,560 --> 00:08:03,240 into my test environment. 173 00:08:03,240 --> 00:08:04,770 Okay. So, that's good. 174 00:08:04,770 --> 00:08:08,070 So, I now have access via the document object, 175 00:08:08,070 --> 00:08:12,840 remember, via the document object provided by Js DOM, 176 00:08:12,840 --> 00:08:15,450 we now have access to that HTML content. 177 00:08:15,450 --> 00:08:17,940 It's loaded in all the price data, effectively, 178 00:08:17,940 --> 00:08:19,773 into my test environment. 179 00:08:20,640 --> 00:08:23,970 But also we've got our JavaScript code, 180 00:08:23,970 --> 00:08:25,540 the actual JavaScript code 181 00:08:27,218 --> 00:08:28,890 lives in another file. 182 00:08:28,890 --> 00:08:30,270 So, like we've been doing 183 00:08:30,270 --> 00:08:33,000 for the, all the different lessons in the past, 184 00:08:33,000 --> 00:08:36,030 we also need to load our JavaScript file 185 00:08:36,030 --> 00:08:38,730 into our test environment as well. 186 00:08:38,730 --> 00:08:41,430 And that's the way that you do that. 187 00:08:41,430 --> 00:08:45,150 Okay. So, when you are using common Js, 188 00:08:45,150 --> 00:08:47,130 so when you're using ECMAScript modules, 189 00:08:47,130 --> 00:08:49,170 that's the way they import symbols. 190 00:08:49,170 --> 00:08:51,450 If you've written any code in React or Angular, 191 00:08:51,450 --> 00:08:54,150 you'd have seen syntax like this 192 00:08:54,150 --> 00:08:56,490 import from my script, 193 00:08:56,490 --> 00:08:59,160 it kind of knows that we're talking about my script, Js, 194 00:08:59,160 --> 00:09:01,170 import the function. 195 00:09:01,170 --> 00:09:04,650 I've imported that function from that file. 196 00:09:04,650 --> 00:09:06,840 When you import a symbol from a file, 197 00:09:06,840 --> 00:09:11,100 it automatically loads that file into the test environment. 198 00:09:11,100 --> 00:09:13,260 So, the HTML content has been loaded 199 00:09:13,260 --> 00:09:14,820 and so has my test code. 200 00:09:14,820 --> 00:09:17,220 What I can then do, is I can write statements 201 00:09:17,220 --> 00:09:22,140 like this document, this variable here document. 202 00:09:22,140 --> 00:09:25,290 That's going to be basically that, 203 00:09:25,290 --> 00:09:27,897 if I can just draw this picture here, 204 00:09:27,897 --> 00:09:30,643 that will point to the route, 205 00:09:30,643 --> 00:09:33,360 the document node in HTML content 206 00:09:33,360 --> 00:09:35,430 that I've read in 207 00:09:35,430 --> 00:09:37,740 The document element will be the HTML. 208 00:09:37,740 --> 00:09:40,500 This will be the entire content of the file. 209 00:09:40,500 --> 00:09:42,090 So, that's basically where the file content 210 00:09:42,090 --> 00:09:43,863 gets loaded in to here. 211 00:09:45,600 --> 00:09:47,730 This statement, that we've already discussed, 212 00:09:47,730 --> 00:09:49,863 is already loaded in the JavaScript code. 213 00:09:50,700 --> 00:09:53,610 So, that means we're now ready to write tests. 214 00:09:53,610 --> 00:09:55,740 Let's write some tests. 215 00:09:55,740 --> 00:09:59,220 So, I call my function, calculateTotalPrice. 216 00:09:59,220 --> 00:10:01,560 So again, let me just draw a quick reminder. 217 00:10:01,560 --> 00:10:03,423 In my, in my test, 218 00:10:05,130 --> 00:10:07,780 my test has basically loaded the HTML content 219 00:10:09,030 --> 00:10:10,713 into the document, 220 00:10:12,240 --> 00:10:13,410 like so. 221 00:10:13,410 --> 00:10:16,530 I've also loaded my calculate total price function, 222 00:10:16,530 --> 00:10:19,200 calculateTotalPrice, like that. 223 00:10:19,200 --> 00:10:20,430 So, that function, 224 00:10:20,430 --> 00:10:23,250 that function is going to be accessing the document. 225 00:10:23,250 --> 00:10:26,190 It'll access the document that we just loaded 226 00:10:26,190 --> 00:10:28,170 and it'll calculate the total price 227 00:10:28,170 --> 00:10:30,118 of elements in that document. 228 00:10:30,118 --> 00:10:31,830 Okay. And it'll give me back a function 229 00:10:31,830 --> 00:10:34,080 just like it would do in a normal environment, 230 00:10:34,080 --> 00:10:35,910 but within our test environment. 231 00:10:35,910 --> 00:10:37,050 And it should give me back, 232 00:10:37,050 --> 00:10:41,400 well it says here the total price should be 1200. 233 00:10:41,400 --> 00:10:46,400 Let's, let's have a quick look to see if we agree with that. 234 00:10:46,500 --> 00:10:48,660 So, I have skis that cost 800 pounds. 235 00:10:48,660 --> 00:10:50,580 That's quite expensive. 236 00:10:50,580 --> 00:10:52,380 Plus 300 pounds for boots. 237 00:10:52,380 --> 00:10:54,090 That's 1100 pounds. 238 00:10:54,090 --> 00:10:55,800 Plus 100 pounds for goggles. 239 00:10:55,800 --> 00:10:57,420 Wow. That's really expensive. 240 00:10:57,420 --> 00:10:59,280 That comes to 1200. 241 00:10:59,280 --> 00:11:01,650 So, if my code is correct, 242 00:11:01,650 --> 00:11:03,570 then it should have loaded the document, 243 00:11:03,570 --> 00:11:05,280 then done the correct algebra 244 00:11:05,280 --> 00:11:07,170 and it should have come up with that figure. 245 00:11:07,170 --> 00:11:09,572 The total price should be 1200. 246 00:11:09,572 --> 00:11:13,620 Okay. So, if I run the tests and it works. 247 00:11:13,620 --> 00:11:16,950 So, just to summarize what we've seen there: 248 00:11:16,950 --> 00:11:21,150 the HTML document contained the actual HTML, 249 00:11:21,150 --> 00:11:24,480 my JavaScript file contained my actual code, 250 00:11:24,480 --> 00:11:28,740 I read the HTML file into Js DOM document, 251 00:11:28,740 --> 00:11:31,050 I imported my JavaScript, 252 00:11:31,050 --> 00:11:32,700 I called the JavaScript, 253 00:11:32,700 --> 00:11:34,590 it accessed the HTML document, 254 00:11:34,590 --> 00:11:36,900 and I've asserted that the result is correct. 255 00:11:36,900 --> 00:11:38,760 So, that basically provides us 256 00:11:38,760 --> 00:11:40,500 with a standard baseline going forward. 257 00:11:40,500 --> 00:11:43,470 This is the way to load the HTML content 258 00:11:43,470 --> 00:11:44,640 and the JavaScript 259 00:11:44,640 --> 00:11:48,330 so that the JavaScript can access the real HTML content. 260 00:11:48,330 --> 00:11:51,753 And it's a viable, useful test.