1 00:00:06,570 --> 00:00:07,410 - In this section, 2 00:00:07,410 --> 00:00:10,620 we're going to investigate static rendering in Enzyme. 3 00:00:10,620 --> 00:00:12,000 We're going to call the render function 4 00:00:12,000 --> 00:00:13,290 with a component. 5 00:00:13,290 --> 00:00:14,970 And it does static rendering. 6 00:00:14,970 --> 00:00:18,030 So, what that means is it'll render the component 7 00:00:18,030 --> 00:00:21,900 plus sub-components but all you get back is the html. 8 00:00:21,900 --> 00:00:25,020 The components have disappeared from the endproduct. 9 00:00:25,020 --> 00:00:27,930 Okay, so, it'll render a component to static HTML, 10 00:00:27,930 --> 00:00:30,990 basically, what the user will see in the webpage. 11 00:00:30,990 --> 00:00:34,230 So you can check that the HTML content is correct, 12 00:00:34,230 --> 00:00:35,880 and that all the elements can interact 13 00:00:35,880 --> 00:00:37,710 with each other properly. 14 00:00:37,710 --> 00:00:39,577 So, the example I'm going to look at is here, 15 00:00:39,577 --> 00:00:41,730 "Enzyme Static, demo-app." 16 00:00:41,730 --> 00:00:45,330 I created the application using the create react app tool, 17 00:00:45,330 --> 00:00:46,950 same application as before, 18 00:00:46,950 --> 00:00:49,770 but this we're gonna be doing static rendering 19 00:00:49,770 --> 00:00:51,330 in our tests. 20 00:00:51,330 --> 00:00:53,070 So, let's have a thing. 21 00:00:53,070 --> 00:00:55,080 The render function is quite different 22 00:00:55,080 --> 00:00:57,420 from the other two we've seen so far. 23 00:00:57,420 --> 00:01:00,393 When we do shallow rendering, with a shallow function, 24 00:01:01,500 --> 00:01:06,500 it'll give us back a- it'll render a component, 25 00:01:06,780 --> 00:01:09,270 the component is still there, 26 00:01:09,270 --> 00:01:12,630 in the result that we get back, 27 00:01:12,630 --> 00:01:14,640 plus the HTML that it renders. 28 00:01:14,640 --> 00:01:15,780 And it's the same for mount. 29 00:01:15,780 --> 00:01:17,310 When we call the mount function, 30 00:01:17,310 --> 00:01:18,870 the components that we rendered, 31 00:01:18,870 --> 00:01:20,430 like product and product this, 32 00:01:20,430 --> 00:01:22,320 they actually still exist, 33 00:01:22,320 --> 00:01:24,570 in the result that we get back. 34 00:01:24,570 --> 00:01:26,790 But when you call the render function, 35 00:01:26,790 --> 00:01:28,290 the components have disappeared. 36 00:01:28,290 --> 00:01:30,930 They get rendered, and they are not present 37 00:01:30,930 --> 00:01:31,920 in the result document. 38 00:01:31,920 --> 00:01:34,350 All you get back is the actual HTML, 39 00:01:34,350 --> 00:01:37,740 literally, just the raw HTML that's going to be displayed 40 00:01:37,740 --> 00:01:38,613 in the browser. 41 00:01:39,690 --> 00:01:43,470 And, you can use a DOM API, CheerioWrapper, 42 00:01:43,470 --> 00:01:45,630 effectively provides a DOM API, 43 00:01:45,630 --> 00:01:48,360 to allow it to access that document content. 44 00:01:48,360 --> 00:01:49,560 So it has classes such as: 45 00:01:49,560 --> 00:01:51,720 Document, you know, for the document node; 46 00:01:51,720 --> 00:01:54,540 Element; Node, that's useful 47 00:01:54,540 --> 00:01:56,430 for representing text elements 48 00:01:56,430 --> 00:01:59,220 for example, text nodes; and so on. 49 00:01:59,220 --> 00:02:01,773 So, let's have a look, the API is here. 50 00:02:02,670 --> 00:02:06,903 Okay, so, there is a Document class provided, 51 00:02:08,160 --> 00:02:11,043 There's an Element class provided, 52 00:02:13,230 --> 00:02:15,270 And it allows you to kind of navigate the content 53 00:02:15,270 --> 00:02:18,090 of the Element, like get its child nodes. 54 00:02:18,090 --> 00:02:20,403 Very much like low-level DOM programming. 55 00:02:21,570 --> 00:02:23,583 There's a Node class. 56 00:02:24,510 --> 00:02:27,480 The Node class allows you to access you know, 57 00:02:27,480 --> 00:02:31,260 the data value in a text node, for example. 58 00:02:31,260 --> 00:02:33,810 So what you'll find using the Cheerio API, 59 00:02:33,810 --> 00:02:35,160 it is quite simple, 60 00:02:35,160 --> 00:02:39,840 you are accessing the HTML using a primitive DOM API. 61 00:02:39,840 --> 00:02:41,730 So, we're going to see how to do that. 62 00:02:41,730 --> 00:02:44,970 Right, so, the classes are the same as we've seen already. 63 00:02:44,970 --> 00:02:48,600 We've had a product item class, there was an app component, 64 00:02:48,600 --> 00:02:51,630 a ProductList component, a product component, 65 00:02:51,630 --> 00:02:53,730 and a TotalValue component. 66 00:02:53,730 --> 00:02:56,220 I'm gonna test the ProductList component. 67 00:02:56,220 --> 00:02:58,590 First of all, without any products. 68 00:02:58,590 --> 00:03:01,980 So, here we are, ProductList test tsx. 69 00:03:01,980 --> 00:03:04,530 I render the ProductList component 70 00:03:04,530 --> 00:03:07,110 with an empty array of products. 71 00:03:07,110 --> 00:03:10,200 Okay, so, probably worthwhile just reminding ourselves 72 00:03:10,200 --> 00:03:12,963 what we actually expect to get back in that scenario. 73 00:03:14,010 --> 00:03:15,660 So, here's the code. 74 00:03:15,660 --> 00:03:20,660 And if you just drill down into the ProductList component... 75 00:03:20,790 --> 00:03:24,150 Okay, so, we see if an array of product items, 76 00:03:24,150 --> 00:03:27,690 if the array is empty, then the HTML that we get back 77 00:03:27,690 --> 00:03:29,190 should be a div. 78 00:03:29,190 --> 00:03:32,527 It has one h1 with this content: 79 00:03:32,527 --> 00:03:34,110 "No products in stock." 80 00:03:34,110 --> 00:03:36,180 Right, let's have a look. 81 00:03:36,180 --> 00:03:38,100 Let's have a look at my test. 82 00:03:38,100 --> 00:03:40,830 So, having rendered that, 83 00:03:40,830 --> 00:03:43,350 we get back a wrapper, a CheerioWrapper. 84 00:03:43,350 --> 00:03:44,880 When you call the find function, 85 00:03:44,880 --> 00:03:47,310 it'll give you back all elements that match. 86 00:03:47,310 --> 00:03:49,260 There should be one element that matches, 87 00:03:49,260 --> 00:03:50,880 there should should be one h1. 88 00:03:50,880 --> 00:03:54,300 The length of this array should be one. 89 00:03:54,300 --> 00:03:57,240 And then you can use indexing to get the first heading. 90 00:03:57,240 --> 00:04:02,240 Okay, so, find element "0" in my collection of h1's. 91 00:04:02,430 --> 00:04:04,530 You gotta be a bit careful with typescript 92 00:04:04,530 --> 00:04:07,110 because we need to clarify variables in typescript. 93 00:04:07,110 --> 00:04:09,240 It needs to know what types things are. 94 00:04:09,240 --> 00:04:10,950 So, I'm using "any" here. 95 00:04:10,950 --> 00:04:14,460 Basically says to the compiler, "don't worry about that." 96 00:04:14,460 --> 00:04:18,690 Right, so, this will hopefully be a pointer 97 00:04:18,690 --> 00:04:19,800 to an h1 element. 98 00:04:19,800 --> 00:04:22,050 You know, the first h1 in the result. 99 00:04:22,050 --> 00:04:26,910 So, h1 element node should point to the h1. 100 00:04:26,910 --> 00:04:28,830 If you only get the text content of it, 101 00:04:28,830 --> 00:04:30,360 you've gotta get its child. 102 00:04:30,360 --> 00:04:33,390 The element has a child node, 103 00:04:33,390 --> 00:04:35,373 and that child node is a text node, 104 00:04:36,240 --> 00:04:39,270 here, and it's that text node that contains the text. 105 00:04:39,270 --> 00:04:43,329 You know, "no products in stock." 106 00:04:43,329 --> 00:04:44,430 Like that. 107 00:04:44,430 --> 00:04:48,090 So, the child, the first child property will give you 108 00:04:48,090 --> 00:04:50,100 back the text node. 109 00:04:50,100 --> 00:04:53,403 So, the text node is that node, there. 110 00:04:54,300 --> 00:04:55,350 All right, good. 111 00:04:55,350 --> 00:04:57,540 And, then, so, it's a bit more involved. 112 00:04:57,540 --> 00:04:58,373 And, then you say like: 113 00:04:58,373 --> 00:04:59,206 "take that text node, 114 00:04:59,206 --> 00:05:01,710 give me the data inside that text node." 115 00:05:01,710 --> 00:05:04,410 It should be "no products in stock." 116 00:05:04,410 --> 00:05:05,280 Okay, so, there you go. 117 00:05:05,280 --> 00:05:10,110 So, it's very low-level DOM API to access the content. 118 00:05:10,110 --> 00:05:12,270 Obviously, we don't have any products, 119 00:05:12,270 --> 00:05:13,740 and we don't have any TotalValue 120 00:05:13,740 --> 00:05:16,650 because there weren't any products in the collection. 121 00:05:16,650 --> 00:05:19,320 So, you know, these counters, the count of these elements, 122 00:05:19,320 --> 00:05:20,313 should be zero. 123 00:05:21,510 --> 00:05:23,640 Right, that's the first test, and the second test is 124 00:05:23,640 --> 00:05:26,473 where we actually pass in some products, 125 00:05:26,473 --> 00:05:27,870 and see what happens. 126 00:05:27,870 --> 00:05:30,750 Let's take a look at this. This is the second test. 127 00:05:30,750 --> 00:05:34,470 So, "ProductList test tsx." 128 00:05:34,470 --> 00:05:36,510 Here's my sample of products, 129 00:05:36,510 --> 00:05:38,100 you've seen that a few times, now. 130 00:05:38,100 --> 00:05:39,690 Here's my second test function. 131 00:05:39,690 --> 00:05:41,973 Let's take a look what's going on here. 132 00:05:43,530 --> 00:05:46,290 Right, so, render, the ProductList component, 133 00:05:46,290 --> 00:05:49,200 it'll render everything underneath it as well, 134 00:05:49,200 --> 00:05:51,093 passing in that product collection. 135 00:05:52,590 --> 00:05:53,887 Again, it's worthwhile thinking, 136 00:05:53,887 --> 00:05:57,030 "what would you expect to get back in that situation?" 137 00:05:57,030 --> 00:05:57,930 Let's have a look. 138 00:05:59,790 --> 00:06:02,280 So, ProductList, here it is. 139 00:06:02,280 --> 00:06:05,730 When you have, like, proper collection passed in, 140 00:06:05,730 --> 00:06:08,040 it should come into the else part. 141 00:06:08,040 --> 00:06:11,580 And in the else part, it should return a div. 142 00:06:11,580 --> 00:06:16,580 The div should have a heading, three products in stock. 143 00:06:16,830 --> 00:06:20,190 And each product should be rendered 144 00:06:20,190 --> 00:06:22,170 using the product component. 145 00:06:22,170 --> 00:06:24,420 Well, let's have a think about that in a moment. 146 00:06:24,420 --> 00:06:27,690 Let's see how can we check that the content we get back 147 00:06:27,690 --> 00:06:29,190 is correct. 148 00:06:29,190 --> 00:06:30,053 Okay, so, what I've done here 149 00:06:30,053 --> 00:06:32,340 is that I've got a dot dot dot. 150 00:06:32,340 --> 00:06:35,730 Okay, so, in my slide, I've kind of missed out 151 00:06:35,730 --> 00:06:36,563 a bit of the testing. 152 00:06:36,563 --> 00:06:39,030 So, if I go to the actual code, we'll see that 153 00:06:39,030 --> 00:06:39,863 the full test. 154 00:06:39,863 --> 00:06:41,010 Let's do that. 155 00:06:41,010 --> 00:06:42,513 All right, so here we are. 156 00:06:43,650 --> 00:06:47,520 So, I get back the content that has been rendered 157 00:06:47,520 --> 00:06:49,653 in all of its HTML goodie. 158 00:06:50,850 --> 00:06:54,120 Find, the collection of h1 elements, 159 00:06:54,120 --> 00:06:55,983 there should be one h1. 160 00:06:57,270 --> 00:06:59,890 Okay, so give me that first h1, 161 00:06:59,890 --> 00:07:01,770 and a 0. 162 00:07:01,770 --> 00:07:04,230 That's my h1 element node. 163 00:07:04,230 --> 00:07:07,350 And from that h1 element, give me the firstChild, 164 00:07:07,350 --> 00:07:08,910 that's the text element. 165 00:07:08,910 --> 00:07:11,130 Watch the text content of that heading. 166 00:07:11,130 --> 00:07:13,167 It should be "3 products in stock." 167 00:07:14,400 --> 00:07:16,140 Okay, now then. 168 00:07:16,140 --> 00:07:17,970 When you call the render function, 169 00:07:17,970 --> 00:07:22,020 it does render everything underneath the component. 170 00:07:22,020 --> 00:07:24,750 It will render all the child content, 171 00:07:24,750 --> 00:07:27,360 it will render three products. 172 00:07:27,360 --> 00:07:30,030 And it will render a TotalValue. 173 00:07:30,030 --> 00:07:32,430 But what you get back, the result you get back, 174 00:07:32,430 --> 00:07:35,190 doesn't contain the actual component itself. 175 00:07:35,190 --> 00:07:38,490 It just contains the result of rendering that component. 176 00:07:38,490 --> 00:07:41,970 Okay, so, even though the product component was invoked, 177 00:07:41,970 --> 00:07:45,030 it isn't present, it is not present in my result list. 178 00:07:45,030 --> 00:07:48,240 All I've got back is what it actually rendered. 179 00:07:48,240 --> 00:07:50,010 So, have a look at this. 180 00:07:50,010 --> 00:07:52,440 In my test, if I check to see 181 00:07:52,440 --> 00:07:55,020 how many product elements there are, 182 00:07:55,020 --> 00:07:56,190 there aren't any. 183 00:07:56,190 --> 00:07:59,250 Okay, my DOM tree doesn't have a product element. 184 00:07:59,250 --> 00:08:03,900 It has been rendered, it's been rendered as a div. 185 00:08:03,900 --> 00:08:07,590 Okay, so, each product component was rendered, 186 00:08:07,590 --> 00:08:12,443 and I should find there are three div productItems. 187 00:08:12,443 --> 00:08:13,276 Okay? 188 00:08:13,276 --> 00:08:14,220 I should find three of those. 189 00:08:14,220 --> 00:08:18,120 Each product component should have rendered itself as, 190 00:08:18,120 --> 00:08:20,460 when I render the product component, 191 00:08:20,460 --> 00:08:23,850 each product component should render itself as 192 00:08:23,850 --> 00:08:27,480 a div with the csx class of productItem. 193 00:08:27,480 --> 00:08:30,570 So, when you are using, when you call the render function, 194 00:08:30,570 --> 00:08:33,180 you don't have access to the components anymore. 195 00:08:33,180 --> 00:08:37,530 You just see what they rendered at the end of the day. 196 00:08:37,530 --> 00:08:40,110 So, my test- let's check that we do actually have 197 00:08:40,110 --> 00:08:41,560 three of these divs. 198 00:08:41,560 --> 00:08:44,730 Three divs with that csx class. Let's check it. 199 00:08:44,730 --> 00:08:46,350 We got that back. 200 00:08:46,350 --> 00:08:49,200 Let's check that in my rendered HTML, 201 00:08:49,200 --> 00:08:52,210 I have three divs with the csx class of "productItem," 202 00:08:52,210 --> 00:08:53,973 there should be three of those. 203 00:08:55,110 --> 00:08:56,430 Okay, hopefully that makes sense. 204 00:08:56,430 --> 00:08:57,907 And then if you want to, you can say, 205 00:08:57,907 --> 00:09:00,660 "well, let's see what's inside those elements, 206 00:09:00,660 --> 00:09:03,780 let's have a look at the first productItem." 207 00:09:03,780 --> 00:09:06,349 So, that's what I'm doing here. 208 00:09:06,349 --> 00:09:09,840 Get my collection of div productItems. 209 00:09:09,840 --> 00:09:11,370 There will be three of those, 210 00:09:11,370 --> 00:09:13,080 because of the three products, 211 00:09:13,080 --> 00:09:16,530 let's get the first one, that'll be the first product. 212 00:09:16,530 --> 00:09:18,960 Okay, so, when I get back here, 213 00:09:18,960 --> 00:09:20,880 the first product will be a div 214 00:09:20,880 --> 00:09:24,300 that contains the render details for the first product. 215 00:09:24,300 --> 00:09:26,010 So effectively, it'll be a div 216 00:09:26,010 --> 00:09:27,990 that contains this information here. 217 00:09:27,990 --> 00:09:31,770 And I'm gonna verify that this content is correct. 218 00:09:31,770 --> 00:09:36,390 Okay, so, that product has a child, 219 00:09:36,390 --> 00:09:38,310 the first child of the product, 220 00:09:38,310 --> 00:09:39,960 now you have to be quite careful here. 221 00:09:39,960 --> 00:09:42,810 You have to be, you have to know where you're at so far. 222 00:09:42,810 --> 00:09:46,470 So, at this point in time, what I've just obtained there, 223 00:09:46,470 --> 00:09:47,523 is the div. 224 00:09:49,020 --> 00:09:52,173 Okay, so, I've basically gained access to the div. 225 00:09:53,940 --> 00:09:57,390 Okay, and then I'm gonna check each of its children. 226 00:09:57,390 --> 00:09:59,610 Okay, I'm gonna check that child, 227 00:09:59,610 --> 00:10:01,560 and then that child, 228 00:10:01,560 --> 00:10:03,420 and then that child. 229 00:10:03,420 --> 00:10:05,340 Okay, so, starting at this div, 230 00:10:05,340 --> 00:10:06,933 let's see what it contains. 231 00:10:10,260 --> 00:10:11,700 Okay, so, that's the div. 232 00:10:11,700 --> 00:10:16,700 Child 0, child 0 is going to be the first element here. 233 00:10:19,980 --> 00:10:23,533 Okay, that's child 0. It's the h2. 234 00:10:24,446 --> 00:10:29,446 And that h2 itself has a child with the text. 235 00:10:29,460 --> 00:10:31,350 So, let's have a look at this, then. 236 00:10:31,350 --> 00:10:33,600 Let's just see what's going on. 237 00:10:33,600 --> 00:10:36,483 So, in my div, get the first child. 238 00:10:38,370 --> 00:10:42,213 Okay, and get the text content inside it. 239 00:10:43,560 --> 00:10:45,570 And that's the h2 text content. 240 00:10:45,570 --> 00:10:48,657 The h2 text content should be "Skis." 241 00:10:50,160 --> 00:10:54,240 So, the h2 child content should be "Skis." 242 00:10:54,240 --> 00:10:55,073 Okay. 243 00:10:55,073 --> 00:10:57,610 Then, we'd say, "get child 1," 244 00:10:57,610 --> 00:10:59,823 let's see what its content is. 245 00:11:01,350 --> 00:11:04,941 Okay, so, let's get on the div, let's get child content 1, 246 00:11:04,941 --> 00:11:07,530 and let's see what its text content is. 247 00:11:07,530 --> 00:11:11,850 Its text content should be "Price: 1000." 248 00:11:11,850 --> 00:11:14,907 So, this should say "Price: 1000." 249 00:11:15,750 --> 00:11:17,670 Good seeing how this is handled together, now. 250 00:11:17,670 --> 00:11:20,880 Finally, we'll get child element 2 from the div. 251 00:11:20,880 --> 00:11:23,400 Now, I'm gonna get child element number two. 252 00:11:23,400 --> 00:11:28,400 Okay, child element 0, child element 1, child element 2, 253 00:11:28,590 --> 00:11:31,500 and let's see what its text content is. 254 00:11:31,500 --> 00:11:33,930 So, this is child element 2. 255 00:11:33,930 --> 00:11:38,760 Its text content should be: "In stock: 5." 256 00:11:38,760 --> 00:11:40,810 Okay, so, that's what we should see here. 257 00:11:42,240 --> 00:11:45,420 In stock, in stock 5. 258 00:11:45,420 --> 00:11:47,880 Obviously, knowing what data I passed in for the product, 259 00:11:47,880 --> 00:11:51,033 I can predict what these strings are actually going to be. 260 00:11:53,520 --> 00:11:56,010 Okay, that's good. 261 00:11:56,010 --> 00:11:57,960 And then finally, don't forget 262 00:11:57,960 --> 00:11:59,340 that at the end of the product, 263 00:11:59,340 --> 00:12:02,130 it also displays the TotalValue. 264 00:12:02,130 --> 00:12:04,620 Remember that? At the end of my product list. 265 00:12:04,620 --> 00:12:06,870 It displays the TotalValue. 266 00:12:06,870 --> 00:12:10,290 This element won't exist, but it will be rendered. 267 00:12:10,290 --> 00:12:13,380 What does it render, and what do we expect? 268 00:12:13,380 --> 00:12:16,860 It should render a div with a csx class, 269 00:12:16,860 --> 00:12:19,980 with a total value of 7000, wasn't it. 270 00:12:19,980 --> 00:12:22,443 Let's check that this div actually exists. 271 00:12:23,610 --> 00:12:27,810 Let's check if I find a div with a total value, 272 00:12:27,810 --> 00:12:29,220 there should be one such element, 273 00:12:29,220 --> 00:12:31,803 one total value at the end of the whole page. 274 00:12:33,060 --> 00:12:35,880 It has a text node, 275 00:12:35,880 --> 00:12:37,867 and the value of that text node should be: 276 00:12:37,867 --> 00:12:40,410 "Total value: 7000." 277 00:12:40,410 --> 00:12:43,620 Okay, so, you have to really understand the DOM, 278 00:12:43,620 --> 00:12:46,020 you have to understand what elements are children 279 00:12:46,020 --> 00:12:49,260 of which elements, and you have to remember as well, 280 00:12:49,260 --> 00:12:52,890 that the text content is also in a separate child. 281 00:12:52,890 --> 00:12:55,053 The text node is one below the element. 282 00:12:56,130 --> 00:12:59,310 Yeah, so it's not difficult, really, it's just, fiddly. 283 00:12:59,310 --> 00:13:01,443 You just have to concentrate. 284 00:13:02,340 --> 00:13:05,880 Now, that's the, that's the summary of what we've just seen. 285 00:13:05,880 --> 00:13:08,880 So, we rendered the product list and all of its content, 286 00:13:08,880 --> 00:13:12,787 and we checked, you know, the headings and so on, 287 00:13:12,787 --> 00:13:17,160 there was no product component in the end result. 288 00:13:17,160 --> 00:13:20,010 Okay, it was rendered, but the product component itself 289 00:13:20,010 --> 00:13:21,870 is not present in the result. 290 00:13:21,870 --> 00:13:26,463 The result of it is, but the product itself isn't there. 291 00:13:27,900 --> 00:13:29,658 Okay, there we are. 292 00:13:29,658 --> 00:13:32,970 And this is the first product, 293 00:13:32,970 --> 00:13:34,627 which I can check the content of, I can say: 294 00:13:34,627 --> 00:13:37,740 "for that product, if I get the first child, 295 00:13:37,740 --> 00:13:41,443 that will be the h2, the text content of that h2 should be: 296 00:13:41,443 --> 00:13:45,117 'skis' and so on, and so on, and so on." 297 00:13:45,960 --> 00:13:49,080 Right, so, you know, quite a lot of code in there, 298 00:13:49,080 --> 00:13:52,409 you have to decide how deep do you want to go 299 00:13:52,409 --> 00:13:53,790 in your testing. 300 00:13:53,790 --> 00:13:55,683 Do you want to check all the content? 301 00:13:56,520 --> 00:13:57,510 Or just part of it? 302 00:13:57,510 --> 00:13:59,850 But, you know, you have access to the whole h2 document, 303 00:13:59,850 --> 00:14:00,930 if you want to. 304 00:14:00,930 --> 00:14:04,680 So, it's just now a matter of running the test 305 00:14:04,680 --> 00:14:06,870 and hoping that it works, 306 00:14:06,870 --> 00:14:08,463 and relax.