1 00:00:06,630 --> 00:00:08,190 - So far in this lesson, 2 00:00:08,190 --> 00:00:10,710 we've been looking at how to use Enzyme 3 00:00:10,710 --> 00:00:12,300 to test React application. 4 00:00:12,300 --> 00:00:15,450 And as we've seen, Enzyme gives us full details 5 00:00:15,450 --> 00:00:18,770 to the internal implementation of a component, 6 00:00:18,770 --> 00:00:20,730 so that we can access its state 7 00:00:20,730 --> 00:00:23,040 and its properties and so on. 8 00:00:23,040 --> 00:00:24,300 The other testing library, 9 00:00:24,300 --> 00:00:26,817 we're going to look at is React Testing Library, 10 00:00:26,817 --> 00:00:30,270 and this has a different emphasis. 11 00:00:30,270 --> 00:00:31,710 With the React Testing Library, 12 00:00:31,710 --> 00:00:34,260 you can't access the internal details. 13 00:00:34,260 --> 00:00:36,240 Instead, you just look at what's been rendered 14 00:00:36,240 --> 00:00:37,800 from the outside. 15 00:00:37,800 --> 00:00:40,770 So it's more like user acceptance testing 16 00:00:40,770 --> 00:00:43,770 rather than unit testing internally. 17 00:00:43,770 --> 00:00:46,680 So the example we're going to look at, it's here. 18 00:00:46,680 --> 00:00:48,540 If you go into lesson 10, 19 00:00:48,540 --> 00:00:52,230 go into this folder React Testing Library demo-app 20 00:00:52,230 --> 00:00:54,810 similar application to before. 21 00:00:54,810 --> 00:00:56,880 So we're gonna look at a few particular files 22 00:00:56,880 --> 00:00:58,080 to see what's going on. 23 00:00:58,080 --> 00:01:00,963 First of all, let's have a look at package.json. 24 00:01:02,190 --> 00:01:05,940 So here's my demo-app, package.json. 25 00:01:05,940 --> 00:01:08,790 I've added some extra dependencies 26 00:01:08,790 --> 00:01:11,790 for testing library, so let's just pick these out. 27 00:01:11,790 --> 00:01:15,780 We have a dependency for testing library. 28 00:01:15,780 --> 00:01:17,940 Well, testing library jest-dom. 29 00:01:17,940 --> 00:01:22,200 We've seen that already and testing library user-event 30 00:01:22,200 --> 00:01:23,910 for simulating events. 31 00:01:23,910 --> 00:01:26,280 And then testing library react. 32 00:01:26,280 --> 00:01:28,020 Okay, so this is what we're gonna be focusing 33 00:01:28,020 --> 00:01:30,150 on in this section. 34 00:01:30,150 --> 00:01:31,980 Also, you might wanna have a look down below 35 00:01:31,980 --> 00:01:34,440 because we're writing in TypeScript. 36 00:01:34,440 --> 00:01:36,990 I've also got some development dependencies here 37 00:01:36,990 --> 00:01:39,150 that give me TypeScript information, 38 00:01:39,150 --> 00:01:41,550 that keeps the TypeScript compiler happy. 39 00:01:41,550 --> 00:01:43,260 I've got type definitions 40 00:01:43,260 --> 00:01:47,580 for jest-dom and for react and for user-event. 41 00:01:47,580 --> 00:01:49,650 Okay, so the TypeScript compiler 42 00:01:49,650 --> 00:01:52,803 will be happy knowing what data type everything is. 43 00:01:53,760 --> 00:01:57,090 Okay, so that's the package.json. 44 00:01:57,090 --> 00:01:59,340 The second file to look at ProductList. 45 00:01:59,340 --> 00:02:01,260 Now, remember this is the component 46 00:02:01,260 --> 00:02:04,080 that render does my list of products. 47 00:02:04,080 --> 00:02:05,580 So I wanna remind you 48 00:02:05,580 --> 00:02:08,760 what we expect to see under various circumstances. 49 00:02:08,760 --> 00:02:10,383 So let's take a look that next. 50 00:02:11,880 --> 00:02:15,903 So in source folder, ProductList tsx. 51 00:02:16,830 --> 00:02:18,390 It's basically the same as we've seen 52 00:02:18,390 --> 00:02:20,880 before the ProductList component. 53 00:02:20,880 --> 00:02:25,020 It receives an array of products and a callback function. 54 00:02:25,020 --> 00:02:27,390 If the minimum or the maximum value changed, 55 00:02:27,390 --> 00:02:30,510 it'll call that function back after rendering. 56 00:02:30,510 --> 00:02:33,240 It uses React State to remember the minimum 57 00:02:33,240 --> 00:02:34,473 and the maximum value. 58 00:02:35,880 --> 00:02:40,238 There's if I scroll down to the user interface part of it. 59 00:02:40,238 --> 00:02:44,880 There is a text box where the user can enter a minimum value 60 00:02:44,880 --> 00:02:47,220 and it'll call this function back if it changes, 61 00:02:47,220 --> 00:02:49,410 if the user types a new value in. 62 00:02:49,410 --> 00:02:52,533 And a text box for the user to enter a maximum value 63 00:02:52,533 --> 00:02:56,010 with the callback function onChangeMax, 64 00:02:56,010 --> 00:02:58,170 those functions are defined up above. 65 00:02:58,170 --> 00:03:00,660 This is the same code as before. 66 00:03:00,660 --> 00:03:04,320 So if the user typed in a different value for the minimum, 67 00:03:04,320 --> 00:03:09,000 we change the value of the minimum value in state 68 00:03:09,000 --> 00:03:11,580 and we change the value of the maximum value. 69 00:03:11,580 --> 00:03:15,840 And my use effect here, my React Hook, it says, 70 00:03:15,840 --> 00:03:18,240 oh, by the way, if either the minimum 71 00:03:18,240 --> 00:03:22,050 or the maximum value changes call this function back. 72 00:03:22,050 --> 00:03:25,380 This call back function is passed into the component 73 00:03:25,380 --> 00:03:27,270 and it calls it if the minimum 74 00:03:27,270 --> 00:03:29,190 or the maximum value is changed. 75 00:03:29,190 --> 00:03:31,410 Okay, when I render my component, 76 00:03:31,410 --> 00:03:33,273 I have to give it a callback function 77 00:03:33,273 --> 00:03:36,273 like it can invoke under these circumstances. 78 00:03:37,380 --> 00:03:42,380 It'll either display a bunch of products or no products, 79 00:03:42,660 --> 00:03:44,700 or it'll display the products here 80 00:03:44,700 --> 00:03:47,340 if there are products, right. 81 00:03:47,340 --> 00:03:48,390 So we've seen that before. 82 00:03:48,390 --> 00:03:50,340 Now, let's have a look at how to test it 83 00:03:50,340 --> 00:03:52,680 using the React Testing Library. 84 00:03:52,680 --> 00:03:55,620 So let's see ProductList test tsx, 85 00:03:55,620 --> 00:03:58,440 this is where we're gonna spend the next few minutes. 86 00:03:58,440 --> 00:04:01,173 So ProductList test tsx. 87 00:04:02,280 --> 00:04:07,280 First of all, I have imported the testing library react. 88 00:04:08,010 --> 00:04:10,170 It gives me a render function 89 00:04:10,170 --> 00:04:12,660 that will allow me to render my content 90 00:04:12,660 --> 00:04:17,250 into like a virtual webpage and a screen object, 91 00:04:17,250 --> 00:04:19,290 which gives me access to that content 92 00:04:19,290 --> 00:04:21,360 after having rendered it. 93 00:04:21,360 --> 00:04:25,770 And then also the user-event library if you remember, 94 00:04:25,770 --> 00:04:28,860 enables me to assimilate events like a button click 95 00:04:28,860 --> 00:04:30,483 and a text box change. 96 00:04:31,690 --> 00:04:34,890 Okay, so then I set up some sample data 97 00:04:34,890 --> 00:04:36,750 and then I've got four tests, 98 00:04:36,750 --> 00:04:39,030 which we're just gonna have a look through. 99 00:04:39,030 --> 00:04:41,400 These four tests just show you 100 00:04:41,400 --> 00:04:43,830 how to use the React Testing Library. 101 00:04:43,830 --> 00:04:45,780 So the easiest test would be 102 00:04:45,780 --> 00:04:49,530 what would be expected at back if there aren't any products, 103 00:04:49,530 --> 00:04:51,150 that's the first test. 104 00:04:51,150 --> 00:04:55,200 So I render my product component 105 00:04:55,200 --> 00:04:57,720 and my ProductList component I should say. 106 00:04:57,720 --> 00:05:00,750 I give it an empty array products 107 00:05:00,750 --> 00:05:03,450 and I give it an empty callback function, okay. 108 00:05:03,450 --> 00:05:05,880 So remember, we've seen this a few times now, 109 00:05:05,880 --> 00:05:08,880 but when you're using jsx or tsx, 110 00:05:08,880 --> 00:05:11,430 when you're in the middle of XML syntax, 111 00:05:11,430 --> 00:05:12,840 you've gotta use the curly brackets 112 00:05:12,840 --> 00:05:15,150 to dip back into JavaScript. 113 00:05:15,150 --> 00:05:18,330 Okay, so an empty array, no products. 114 00:05:18,330 --> 00:05:22,020 The callback function is an empty function. 115 00:05:22,020 --> 00:05:23,880 Okay, so basically it'll call that function, 116 00:05:23,880 --> 00:05:26,190 it does nothing, right. 117 00:05:26,190 --> 00:05:27,900 What would we expect to get back 118 00:05:27,900 --> 00:05:30,360 if we render an empty product list? 119 00:05:30,360 --> 00:05:33,240 Well, we kind of know this already. 120 00:05:33,240 --> 00:05:34,920 If the product list is empty 121 00:05:34,920 --> 00:05:38,940 then this is the HTML that we should get back. 122 00:05:38,940 --> 00:05:43,020 Okay, a div an h1, no products in stock. 123 00:05:43,020 --> 00:05:44,490 Now testing library, 124 00:05:44,490 --> 00:05:46,080 this is how you use it. 125 00:05:46,080 --> 00:05:48,870 Remember, the render function will render 126 00:05:48,870 --> 00:05:52,500 into a virtual webpage screen 127 00:05:52,500 --> 00:05:56,100 is the document body property in that virtual webpage. 128 00:05:56,100 --> 00:05:58,680 So basically in my document body, 129 00:05:58,680 --> 00:06:02,730 find an element that has this text queryByText. 130 00:06:02,730 --> 00:06:07,230 This is the function like a high-level testing 131 00:06:07,230 --> 00:06:08,700 by what the user will see. 132 00:06:08,700 --> 00:06:13,700 Find an element, which has this text, no products in stock. 133 00:06:16,020 --> 00:06:17,640 That's a regular expression 134 00:06:17,640 --> 00:06:19,530 and it's case insensitive. 135 00:06:19,530 --> 00:06:21,990 Find an element with that text 136 00:06:21,990 --> 00:06:25,230 and verify that such an element actually did exist. 137 00:06:25,230 --> 00:06:28,317 Okay, so did my ProductList render 138 00:06:28,317 --> 00:06:30,630 and h1 no products in stock? 139 00:06:30,630 --> 00:06:32,730 That's what I'm testing there. 140 00:06:32,730 --> 00:06:33,900 That was easy enough. 141 00:06:33,900 --> 00:06:36,360 Let's go into the second test. 142 00:06:36,360 --> 00:06:39,300 Second test is where I do have some products 143 00:06:39,300 --> 00:06:42,900 and I should get back a list of products being displayed. 144 00:06:42,900 --> 00:06:44,400 Okay, little bit more involved. 145 00:06:44,400 --> 00:06:45,570 Same idea though. 146 00:06:45,570 --> 00:06:48,300 Render products with a ProductList 147 00:06:48,300 --> 00:06:49,920 with a actual array products. 148 00:06:49,920 --> 00:06:51,870 There were three of them. 149 00:06:51,870 --> 00:06:56,310 When we do that, what should we expect to get back? 150 00:06:56,310 --> 00:07:00,810 Well, we should come into here in my ProductList component. 151 00:07:00,810 --> 00:07:03,390 It should come into here and it should render, 152 00:07:03,390 --> 00:07:04,983 or basically three products. 153 00:07:06,420 --> 00:07:09,510 Plus a total value that should now be rendered. 154 00:07:09,510 --> 00:07:11,430 And it is all rendered. 155 00:07:11,430 --> 00:07:13,833 We just get to see the HTML after the event. 156 00:07:15,000 --> 00:07:17,640 So let's see what the HTML look like. 157 00:07:17,640 --> 00:07:19,560 Let's grab the document body 158 00:07:19,560 --> 00:07:24,560 and let's try to find elements 3 products in stock. 159 00:07:25,260 --> 00:07:28,260 Remember when you call these query functions, 160 00:07:28,260 --> 00:07:29,460 it just gives you back. 161 00:07:29,460 --> 00:07:31,680 It assumes there's gonna be one match. 162 00:07:31,680 --> 00:07:34,890 Find an element and there must be just one 163 00:07:34,890 --> 00:07:37,260 that matches this text. 164 00:07:37,260 --> 00:07:38,460 3 products in stock. 165 00:07:38,460 --> 00:07:40,860 Is that an element is the one element 166 00:07:40,860 --> 00:07:43,050 that contains that text. 167 00:07:43,050 --> 00:07:46,080 There should be one element that contains that text. 168 00:07:46,080 --> 00:07:50,853 Okay, and obviously, that's going to be this element here. 169 00:07:52,200 --> 00:07:53,033 Okay. Right. 170 00:07:53,033 --> 00:07:55,410 Let's go back to the rest of it here. 171 00:07:55,410 --> 00:08:00,090 Now get all means give me back all elements. 172 00:08:00,090 --> 00:08:01,743 This is how you find headings. 173 00:08:02,910 --> 00:08:06,900 Give me back a collection of all age one headings, 174 00:08:06,900 --> 00:08:08,640 the query API. 175 00:08:08,640 --> 00:08:11,190 This is basically the area syntax. 176 00:08:11,190 --> 00:08:14,400 Find all elements that have the heading roll. 177 00:08:14,400 --> 00:08:16,803 Heading in other words h2's. 178 00:08:17,970 --> 00:08:20,313 How many h2 do we expect to get back? 179 00:08:21,510 --> 00:08:23,220 Interesting question. 180 00:08:23,220 --> 00:08:24,390 Well, let's think about it. 181 00:08:24,390 --> 00:08:25,833 We've got three products. 182 00:08:26,760 --> 00:08:31,760 Each product will be rendered by the product component. 183 00:08:31,890 --> 00:08:34,920 The product component for each product, 184 00:08:34,920 --> 00:08:38,910 it will render an h2, the product description. 185 00:08:38,910 --> 00:08:41,820 So three products altogether we should find 186 00:08:41,820 --> 00:08:43,620 in the resulting webpage. 187 00:08:43,620 --> 00:08:48,573 There should be three elements of type h2. 188 00:08:50,430 --> 00:08:53,490 Get all elements, which h2's. 189 00:08:53,490 --> 00:08:55,320 The length of the collection that comes back. 190 00:08:55,320 --> 00:08:59,940 There should be three h2's for the three different products. 191 00:08:59,940 --> 00:09:02,370 Get the first of those h2's. 192 00:09:02,370 --> 00:09:04,410 Effectively, what I'm doing here 193 00:09:04,410 --> 00:09:07,425 is I'm getting this h2 here. 194 00:09:07,425 --> 00:09:09,213 Okay, the h2 for the first product. 195 00:09:11,310 --> 00:09:14,523 Get it's in HTML and it should be skis. 196 00:09:16,680 --> 00:09:19,320 It should contain skis, okay. 197 00:09:19,320 --> 00:09:21,060 When you do a regular expression match, 198 00:09:21,060 --> 00:09:25,353 you're saying does the text somewhere contain skis? 199 00:09:26,250 --> 00:09:28,923 The second heading should contain the text boots. 200 00:09:29,910 --> 00:09:30,840 And then the third heading 201 00:09:30,840 --> 00:09:33,450 or heading three starting at zero 202 00:09:33,450 --> 00:09:35,760 should contain the text goggles. 203 00:09:35,760 --> 00:09:40,760 Oh! And also find one element that contains this text. 204 00:09:41,550 --> 00:09:45,330 The total value should be 7,000 based on the sample data 205 00:09:45,330 --> 00:09:46,890 that we passed in. 206 00:09:46,890 --> 00:09:50,100 Okay, so verify that there wasn't element 207 00:09:50,100 --> 00:09:52,140 that contained the text 7,000. 208 00:09:52,140 --> 00:09:56,100 Of course, what that's going to be the total value displayed 209 00:09:56,100 --> 00:09:58,143 at the end 7,000. 210 00:09:59,040 --> 00:10:00,480 Okay, so you get a feeling 211 00:10:00,480 --> 00:10:03,420 for how this works with React Dom. 212 00:10:03,420 --> 00:10:06,090 You're searching just for the HTML content. 213 00:10:06,090 --> 00:10:08,310 And you're searching based on the kind of text 214 00:10:08,310 --> 00:10:10,290 that the user sees on the webpage 215 00:10:10,290 --> 00:10:14,040 rather than something more internal, right. 216 00:10:14,040 --> 00:10:16,350 Two more tests to look at and then we're finished, 217 00:10:16,350 --> 00:10:19,620 oh, what should happen if the user 218 00:10:19,620 --> 00:10:21,603 has specified a minimum price? 219 00:10:22,710 --> 00:10:24,000 Good question. 220 00:10:24,000 --> 00:10:27,990 We need to emulate the user type in a minimum price, 221 00:10:27,990 --> 00:10:30,963 render the ProductList with three products. 222 00:10:32,730 --> 00:10:37,730 Get a text box accompanied by the minimum price label. 223 00:10:37,740 --> 00:10:42,540 Right. Remember what my ProductList looked like? 224 00:10:42,540 --> 00:10:45,810 There was a label that said minimum price. 225 00:10:45,810 --> 00:10:48,090 I basically wanted to get the text box associated 226 00:10:48,090 --> 00:10:49,053 with that label. 227 00:10:49,920 --> 00:10:51,450 That's what I've done here. 228 00:10:51,450 --> 00:10:53,490 Find the label minimum price 229 00:10:53,490 --> 00:10:57,030 and give me back the text box associated with it. 230 00:10:57,030 --> 00:11:01,683 Into that text box, simulate the user typing this. Okay. 231 00:11:04,560 --> 00:11:09,560 So we're basically specifying into the minimum text box, 232 00:11:09,900 --> 00:11:13,500 simulate that event as if the user had typed in 101 233 00:11:13,500 --> 00:11:14,940 into that text box. 234 00:11:14,940 --> 00:11:16,890 Lots of things should happen 235 00:11:16,890 --> 00:11:20,777 that should filter the products just to display products 236 00:11:20,777 --> 00:11:22,437 across more than 101. 237 00:11:22,437 --> 00:11:26,520 But in my actual application, if I did it in reality 238 00:11:26,520 --> 00:11:27,840 that's what would actually come back. 239 00:11:27,840 --> 00:11:31,920 And that's what we're gonna test does come back in our test. 240 00:11:31,920 --> 00:11:34,950 So we should get back two products with a total price 241 00:11:34,950 --> 00:11:37,350 of 6,000 altogether, right. 242 00:11:37,350 --> 00:11:39,330 That's quite exciting, isn't it? 243 00:11:39,330 --> 00:11:41,283 Get all heading tools, 244 00:11:42,150 --> 00:11:47,150 so each of those products had an h2, there was an h2, 245 00:11:47,790 --> 00:11:52,590 there was an h2, there should be two h2, 246 00:11:52,590 --> 00:11:55,143 two products that cost more than 101. 247 00:11:56,220 --> 00:11:59,440 The first heading should say skis 248 00:12:00,570 --> 00:12:02,280 that costs more than 100. 249 00:12:02,280 --> 00:12:05,160 The second heading should say boots, 250 00:12:05,160 --> 00:12:08,040 because boots also cost more than 100. 251 00:12:08,040 --> 00:12:12,060 Get the element that contains total value 252 00:12:12,060 --> 00:12:13,350 and it should be 6,000. 253 00:12:13,350 --> 00:12:14,400 Effectively, what I'm doing here 254 00:12:14,400 --> 00:12:17,490 is I'm finding this element in my total value component. 255 00:12:17,490 --> 00:12:18,820 We're finding this div 256 00:12:20,010 --> 00:12:22,660 and we checking that the total value is indeed 6,000. 257 00:12:25,590 --> 00:12:27,750 Okay! Right! 258 00:12:27,750 --> 00:12:30,570 Same idea, but specifying a maximum price. 259 00:12:30,570 --> 00:12:31,593 Let's go into here. 260 00:12:32,460 --> 00:12:34,160 This is gonna be our last example. 261 00:12:35,160 --> 00:12:37,623 Right, so render the products. 262 00:12:38,880 --> 00:12:43,880 Get the text box associated with this label, maximum price. 263 00:12:44,700 --> 00:12:49,700 So again, in my ProductList there's the label maximum price, 264 00:12:51,360 --> 00:12:54,209 there's the text box associated with it. 265 00:12:54,209 --> 00:12:55,809 Okay, so we've got that text box 266 00:12:56,910 --> 00:13:01,177 and into that text box simulate the user type in 999. 267 00:13:02,430 --> 00:13:06,453 Well, in my real application, what would that actually do? 268 00:13:09,000 --> 00:13:11,040 999, right. 269 00:13:11,040 --> 00:13:13,590 So we should get back ski, boots, and goggles, 270 00:13:13,590 --> 00:13:15,300 a total price of 2,000. 271 00:13:15,300 --> 00:13:18,300 I feel like I wanna go on a skiing holiday again. 272 00:13:18,300 --> 00:13:20,490 Anyway, more of that later. 273 00:13:20,490 --> 00:13:24,120 So how many h2 is do we get back? 274 00:13:24,120 --> 00:13:26,280 There should have been two of them. 275 00:13:26,280 --> 00:13:30,183 The first h2, the first product, boots. 276 00:13:31,260 --> 00:13:35,430 And the second product is goggles. 277 00:13:35,430 --> 00:13:36,510 There we go. 278 00:13:36,510 --> 00:13:39,090 Goggles, boots and goggles. 279 00:13:39,090 --> 00:13:40,680 Essential when you go skiing. 280 00:13:40,680 --> 00:13:43,113 Also skis are essential as well. 281 00:13:44,130 --> 00:13:49,130 And get the element that contains 282 00:13:49,380 --> 00:13:51,540 that text total value 2,000. 283 00:13:51,540 --> 00:13:53,690 Verify that did actually just... 284 00:13:54,660 --> 00:13:57,300 There we are, so using the React library 285 00:13:57,300 --> 00:13:59,190 where using functions like this, 286 00:13:59,190 --> 00:14:01,023 you'll find it elements by roll. 287 00:14:02,040 --> 00:14:05,583 Like I've done here or by label text, 288 00:14:07,800 --> 00:14:10,713 and then check in the value that they contain. 289 00:14:12,150 --> 00:14:14,340 Very good, so all we need to do now 290 00:14:14,340 --> 00:14:18,690 is to run the test and have a party 291 00:14:18,690 --> 00:14:21,000 because it's worked and that's the end of the lesson. 292 00:14:21,000 --> 00:14:23,580 So we've seen a lot in this lesson. 293 00:14:23,580 --> 00:14:26,640 We started off looking at the basics of React testing. 294 00:14:26,640 --> 00:14:27,473 And by the end of it, 295 00:14:27,473 --> 00:14:30,360 we've seen quite a detailed look at Enzyme 296 00:14:30,360 --> 00:14:33,510 for unit testing and then the React Testing Library 297 00:14:33,510 --> 00:14:35,910 for more kind of user acceptance testing 298 00:14:35,910 --> 00:14:38,583 to verify that the webpage actually looks beautiful.