1 00:00:06,660 --> 00:00:09,210 - In React, a functional component 2 00:00:09,210 --> 00:00:12,630 can store and modify state during its lifetime. 3 00:00:12,630 --> 00:00:15,510 For example, it could have a hit count 4 00:00:15,510 --> 00:00:17,070 and every time the user click the button 5 00:00:17,070 --> 00:00:18,990 it could increment the hit count. 6 00:00:18,990 --> 00:00:21,790 So the component would need to store the value somewhere 7 00:00:22,710 --> 00:00:24,690 and the thing is it couldn't just store that value 8 00:00:24,690 --> 00:00:27,000 in a local variable inside the function 9 00:00:27,000 --> 00:00:30,510 because every time the function ends 10 00:00:30,510 --> 00:00:32,280 that local variable will be lost. 11 00:00:32,280 --> 00:00:35,460 So, functional components need somewhere else 12 00:00:35,460 --> 00:00:37,950 where they can store persistent data 13 00:00:37,950 --> 00:00:39,930 and these days in React 14 00:00:39,930 --> 00:00:42,180 we have this mechanism called a state hook. 15 00:00:42,180 --> 00:00:44,820 Basically you hand the value over to React 16 00:00:44,820 --> 00:00:47,640 and React stores the value permanently 17 00:00:47,640 --> 00:00:49,830 whilst the component is alive. 18 00:00:49,830 --> 00:00:54,570 So to use state hooks, we have a useState function. 19 00:00:54,570 --> 00:00:56,910 You call this function in your component 20 00:00:56,910 --> 00:00:59,100 when you are first rendered. 21 00:00:59,100 --> 00:01:00,450 When you call that function 22 00:01:01,380 --> 00:01:02,760 you give it the initial value 23 00:01:02,760 --> 00:01:05,220 that you would like for your variable 24 00:01:05,220 --> 00:01:09,000 and then the useState function what it does it grabs. 25 00:01:09,000 --> 00:01:13,263 Imagine that this kind of blob here, is React memory. 26 00:01:14,160 --> 00:01:15,960 When you call the useState function, 27 00:01:16,860 --> 00:01:21,150 React allocates a chunk of memory in there, 28 00:01:21,150 --> 00:01:22,860 whatever the initial value is 29 00:01:22,860 --> 00:01:24,720 it puts that value into there. 30 00:01:24,720 --> 00:01:25,923 Let's say it's zero. 31 00:01:27,030 --> 00:01:28,320 Okay, like that. 32 00:01:28,320 --> 00:01:30,330 And then what the function returns back 33 00:01:30,330 --> 00:01:31,800 it returns back two values. 34 00:01:31,800 --> 00:01:34,713 It actually returns back an array of two outputs. 35 00:01:36,090 --> 00:01:39,570 So we have the first element in array, 36 00:01:39,570 --> 00:01:40,893 I've called it stateVar. 37 00:01:42,247 --> 00:01:44,640 Basically that's the current value 38 00:01:44,640 --> 00:01:48,093 of your state variable, so it's zero initially. 39 00:01:49,080 --> 00:01:50,670 The next element in the array 40 00:01:50,670 --> 00:01:53,700 or the next item it returns back, updateFunc, 41 00:01:53,700 --> 00:01:56,820 I've put it into a variable called updateFunc. 42 00:01:56,820 --> 00:01:59,010 That's interesting. 43 00:01:59,010 --> 00:02:03,933 That's a pointer to a callback function provided by React. 44 00:02:04,980 --> 00:02:08,070 React has a callback function to say 45 00:02:08,070 --> 00:02:11,790 if you ever need to change the value, call this function 46 00:02:11,790 --> 00:02:14,643 and it gives you a pointer to that function. 47 00:02:15,540 --> 00:02:17,520 So whenever you wanna change the value 48 00:02:17,520 --> 00:02:21,120 you've gotta call that function with the new value. 49 00:02:21,120 --> 00:02:25,293 So that's what you get back when you call React.useState. 50 00:02:26,250 --> 00:02:30,240 So if you wanted to display the value of your variable 51 00:02:30,240 --> 00:02:31,863 you can just use stateVar. 52 00:02:33,284 --> 00:02:36,750 So stateVar, that's the current value of the variable, 53 00:02:36,750 --> 00:02:39,210 you can just display that on your webpage. 54 00:02:39,210 --> 00:02:40,890 If you've had to change the value, 55 00:02:40,890 --> 00:02:42,900 then you have to call the update function. 56 00:02:42,900 --> 00:02:44,490 You call the update function 57 00:02:44,490 --> 00:02:45,990 and you pass in the new value. 58 00:02:46,980 --> 00:02:48,153 So let's say it's one. 59 00:02:49,050 --> 00:02:50,760 React would store the new value 60 00:02:50,760 --> 00:02:53,940 in it's internal memory, like that. 61 00:02:53,940 --> 00:02:56,520 So the value is now going to be one. 62 00:02:56,520 --> 00:02:58,620 And also because React realizes 63 00:02:58,620 --> 00:03:00,570 that you've just changed the state, 64 00:03:00,570 --> 00:03:04,050 React will automatically re-render your component 65 00:03:04,050 --> 00:03:05,460 with the new value. 66 00:03:05,460 --> 00:03:08,730 That's why it's important that you call the function. 67 00:03:08,730 --> 00:03:10,980 By calling the function you're notifying React 68 00:03:10,980 --> 00:03:12,270 that the value has changed 69 00:03:12,270 --> 00:03:14,700 so that it can re-render your component 70 00:03:14,700 --> 00:03:15,990 with the new value. 71 00:03:15,990 --> 00:03:16,890 So that's great. 72 00:03:16,890 --> 00:03:19,800 That mechanism is basically how you store values 73 00:03:19,800 --> 00:03:23,910 in a kind of semi-permanent basis in a React component. 74 00:03:23,910 --> 00:03:25,140 The example we're gonna look at 75 00:03:25,140 --> 00:03:27,750 is gonna see how to test that mechanism. 76 00:03:27,750 --> 00:03:30,360 How can I verify that my component 77 00:03:30,360 --> 00:03:32,730 does update the value when it should 78 00:03:32,730 --> 00:03:36,060 based on a new user for the minimum text box. 79 00:03:36,060 --> 00:03:39,630 So for example, the Enzyme_State folder in lesson 10, 80 00:03:39,630 --> 00:03:41,730 I've got a demo application, 81 00:03:41,730 --> 00:03:44,640 it's similar to the application we've seen before. 82 00:03:44,640 --> 00:03:46,350 It has a ProductList component, 83 00:03:46,350 --> 00:03:48,390 displays a bunch of products. 84 00:03:48,390 --> 00:03:50,020 There are a couple of text boxes 85 00:03:50,880 --> 00:03:52,740 which allow the user to specify 86 00:03:52,740 --> 00:03:55,230 a minimum and a maximum value. 87 00:03:55,230 --> 00:03:59,280 My component stores those values in state 88 00:03:59,280 --> 00:04:03,180 and then when the user types in a new value in a text box, 89 00:04:03,180 --> 00:04:05,160 it updates those values. 90 00:04:05,160 --> 00:04:08,970 It updates the value of min and max in React state 91 00:04:08,970 --> 00:04:12,240 and then that causes the component to be re-rendered. 92 00:04:12,240 --> 00:04:15,840 Automatically whenever you change state in a React component 93 00:04:15,840 --> 00:04:17,987 React will automatically refresh your component. 94 00:04:17,987 --> 00:04:22,740 It'll re-render it with a filtered list of products. 95 00:04:22,740 --> 00:04:24,300 So the demo application, 96 00:04:24,300 --> 00:04:27,420 I'm just gonna run it quickly just to remind you 97 00:04:27,420 --> 00:04:28,530 and here it is. 98 00:04:28,530 --> 00:04:32,040 If you go into the Enzyme_State demo app folder, 99 00:04:32,040 --> 00:04:36,150 npm-install, npm-run or npm-start, 100 00:04:36,150 --> 00:04:39,420 and then we've got here all products displayed initially. 101 00:04:39,420 --> 00:04:43,473 Let's set the minimum price to be 300. 102 00:04:45,060 --> 00:04:49,710 Let's set the maximum price to be 500. 103 00:04:49,710 --> 00:04:53,730 So there you can see, as we type values in, it works. 104 00:04:53,730 --> 00:04:57,033 What I'm gonna do now is to test the code that does that. 105 00:04:58,560 --> 00:04:59,610 So a quick reminder 106 00:04:59,610 --> 00:05:03,210 here's the code in my ProductList component. 107 00:05:03,210 --> 00:05:04,230 First thing it does 108 00:05:04,230 --> 00:05:07,380 is to say I would like to store a value, the minimum value, 109 00:05:07,380 --> 00:05:08,613 in React state. 110 00:05:09,570 --> 00:05:12,390 This variable is the current value of minimum. 111 00:05:12,390 --> 00:05:13,830 This is a pointer to a function 112 00:05:13,830 --> 00:05:15,480 that I've gotta call to change it 113 00:05:16,440 --> 00:05:17,760 and the same for the maximum. 114 00:05:17,760 --> 00:05:19,410 The maximum value initially 115 00:05:19,410 --> 00:05:21,213 or the default max is a million, 116 00:05:22,080 --> 00:05:24,120 so that's the default maximum. 117 00:05:24,120 --> 00:05:25,770 If I want to change the value 118 00:05:25,770 --> 00:05:27,603 that's the function to invoke. 119 00:05:28,560 --> 00:05:31,560 The text boxes are down below. 120 00:05:31,560 --> 00:05:35,640 If I scroll down in my component, there's a text box here. 121 00:05:35,640 --> 00:05:38,940 If the user types in the value, that's the minimum text box. 122 00:05:38,940 --> 00:05:40,650 If the user types in the value 123 00:05:40,650 --> 00:05:44,160 it calls back this function in my component 124 00:05:44,160 --> 00:05:47,077 and that's up here, onChangeMin. 125 00:05:49,050 --> 00:05:51,810 So when the user types in the value for the text box, 126 00:05:51,810 --> 00:05:53,880 this function gets invoked. 127 00:05:53,880 --> 00:05:57,570 It grabs the value entered from the user in the text box 128 00:05:57,570 --> 00:05:59,610 or zero, if it was empty, 129 00:05:59,610 --> 00:06:02,280 and then it calls the callback function. 130 00:06:02,280 --> 00:06:04,170 So this is what I'm gonna test. 131 00:06:04,170 --> 00:06:06,510 This is gonna be the purpose of my test, 132 00:06:06,510 --> 00:06:10,530 simulate the user entering a value in the minimum text box 133 00:06:10,530 --> 00:06:13,443 and then test that this function was invoked. 134 00:06:14,340 --> 00:06:17,010 Check that the setMin function was invoked 135 00:06:17,010 --> 00:06:18,660 or the setMax function was invoked, 136 00:06:18,660 --> 00:06:22,530 basically I'm testing whether my component updates React 137 00:06:22,530 --> 00:06:24,960 with the value entered by the user. 138 00:06:24,960 --> 00:06:28,020 When the user enters the value in the text box 139 00:06:28,020 --> 00:06:32,310 test that my component sends the new value to React 140 00:06:32,310 --> 00:06:34,830 by calling the appropriate updated function 141 00:06:34,830 --> 00:06:37,006 in React.useState. 142 00:06:37,006 --> 00:06:40,140 Now then, in order to test state in Enzyme 143 00:06:40,140 --> 00:06:43,530 it's a bit tricky because this state hook 144 00:06:43,530 --> 00:06:47,700 is an entirely internal mechanism managed by React 145 00:06:47,700 --> 00:06:51,000 and Enzyme application has no direct access 146 00:06:51,000 --> 00:06:52,800 to the state mechanism. 147 00:06:52,800 --> 00:06:57,600 So we have to be a bit more clever about things. 148 00:06:57,600 --> 00:07:00,060 What I can do is detect 149 00:07:00,060 --> 00:07:02,130 if the update state function was called, 150 00:07:02,130 --> 00:07:05,730 in other words, did my code called the setMin function 151 00:07:05,730 --> 00:07:08,670 or the setMax function when it should have done. 152 00:07:08,670 --> 00:07:12,510 So here is the code that I'm going to use to detect 153 00:07:12,510 --> 00:07:15,210 whether my update functions are invoked. 154 00:07:15,210 --> 00:07:16,650 It's quite interesting. 155 00:07:16,650 --> 00:07:19,020 So I'm just gonna draw a picture, first of all, 156 00:07:19,020 --> 00:07:21,840 to show what happens in the normal circumstance, 157 00:07:21,840 --> 00:07:23,610 and then I'll draw a picture to show 158 00:07:23,610 --> 00:07:26,670 what's happening here where we are mocking things. 159 00:07:26,670 --> 00:07:28,890 So under normal circumstances 160 00:07:28,890 --> 00:07:32,370 when my component is rendered 161 00:07:32,370 --> 00:07:35,550 it called the React.useState function, 162 00:07:35,550 --> 00:07:38,490 React.useState as we've just seen, 163 00:07:38,490 --> 00:07:40,580 and specified for the minimum value, 164 00:07:40,580 --> 00:07:43,590 it specified an initial value of zero. 165 00:07:43,590 --> 00:07:44,820 Let's see. 166 00:07:44,820 --> 00:07:47,100 Okay, so we've seen that. 167 00:07:47,100 --> 00:07:50,190 And what we've seen is that React internally 168 00:07:50,190 --> 00:07:53,790 sets aside a bit of storage to hold that value 169 00:07:53,790 --> 00:07:58,320 and what it gives me back is a variable 170 00:07:58,320 --> 00:08:02,370 that will hold the initial value, as specified zero, 171 00:08:02,370 --> 00:08:04,920 and also a pointer to a function 172 00:08:04,920 --> 00:08:07,563 that I can invoke back again afterwards. 173 00:08:10,657 --> 00:08:12,390 That's what I'd normally get back 174 00:08:12,390 --> 00:08:14,070 when I call React.useState, 175 00:08:14,070 --> 00:08:15,420 I get back an array. 176 00:08:15,420 --> 00:08:19,110 The first element is the current value of my variable 177 00:08:19,110 --> 00:08:21,450 and the second element is a callback function 178 00:08:21,450 --> 00:08:26,070 that I can invoke to tell React when the value changes. 179 00:08:26,070 --> 00:08:27,960 This is what I want to test. 180 00:08:27,960 --> 00:08:32,610 I want to test is this function being invoked properly 181 00:08:32,610 --> 00:08:35,520 when the user enters a new value in the text box. 182 00:08:35,520 --> 00:08:39,000 So let's see what happens in my test. 183 00:08:39,000 --> 00:08:40,410 Let's see. 184 00:08:40,410 --> 00:08:42,000 So what I'm gonna do is I'm gonna define 185 00:08:42,000 --> 00:08:44,073 a mock state update function. 186 00:08:45,060 --> 00:08:47,460 Basically I'm gonna provide a mock version 187 00:08:47,460 --> 00:08:48,453 of this function. 188 00:08:50,580 --> 00:08:52,140 Because I wanna basically simulate 189 00:08:52,140 --> 00:08:54,120 what's happening in React.useState, 190 00:08:54,120 --> 00:08:57,510 I'm providing a mock version of that function. 191 00:08:57,510 --> 00:09:01,360 This is a mock version of the callback function 192 00:09:03,432 --> 00:09:06,090 that would hopefully be invoked 193 00:09:06,090 --> 00:09:09,210 when the user types in a new value for the minimum. 194 00:09:09,210 --> 00:09:10,710 So bear that in mind. 195 00:09:10,710 --> 00:09:11,970 What's next? 196 00:09:11,970 --> 00:09:13,200 Well the second thing I'm doing 197 00:09:13,200 --> 00:09:15,060 is I'm actually intercepting, 198 00:09:15,060 --> 00:09:17,610 I'm actually gonna provide a mock implementation 199 00:09:17,610 --> 00:09:21,750 of the React.useState function in the React module. 200 00:09:21,750 --> 00:09:23,100 I'm going to emulate. 201 00:09:23,100 --> 00:09:25,920 I'm gonna provide a mock for the useState function. 202 00:09:25,920 --> 00:09:29,490 So when my component thinks it's calling React.useState 203 00:09:29,490 --> 00:09:33,060 in fact, it's not, it's going to be calling a mock, 204 00:09:33,060 --> 00:09:34,650 I've got a mock or a spike. 205 00:09:34,650 --> 00:09:37,860 It's gonna be calling something else instead. 206 00:09:37,860 --> 00:09:40,590 I've mocked the useState function. 207 00:09:40,590 --> 00:09:42,570 I've mocked the useState function, 208 00:09:42,570 --> 00:09:44,280 the React.useState function 209 00:09:44,280 --> 00:09:48,120 so that when it's invoked, the mock version of my function, 210 00:09:48,120 --> 00:09:50,100 which I'll just kind of draw right here, 211 00:09:50,100 --> 00:09:52,920 a mock version of React.useState, 212 00:09:52,920 --> 00:09:56,160 it will be a simple do-nothing function 213 00:09:56,160 --> 00:09:59,760 that returns an array, a mock array basically, 214 00:09:59,760 --> 00:10:01,060 it'll return a mock array 215 00:10:02,070 --> 00:10:05,260 with the value zero for the current value 216 00:10:06,210 --> 00:10:09,923 and a pointer to the mock callback function there. 217 00:10:12,630 --> 00:10:14,150 There you go. 218 00:10:14,150 --> 00:10:17,670 So when my component calls React.useState, 219 00:10:17,670 --> 00:10:20,403 it won't be actually calling React.useState anymore, 220 00:10:21,330 --> 00:10:24,880 it'll be calling my mock version of React.useState 221 00:10:26,250 --> 00:10:29,220 and what my mock version of React.useState does, 222 00:10:29,220 --> 00:10:32,910 it says, if you want to change the value of the state 223 00:10:32,910 --> 00:10:34,323 call this function. 224 00:10:35,490 --> 00:10:40,350 So basically I've hooked up my mock setMin function here. 225 00:10:40,350 --> 00:10:43,380 That is the function that my component thinks 226 00:10:43,380 --> 00:10:47,370 it needs to call whenever the value changes. 227 00:10:47,370 --> 00:10:48,630 The setMin function 228 00:10:48,630 --> 00:10:50,490 is basically my mock function here. 229 00:10:50,490 --> 00:10:52,980 The real functions that React might have provided 230 00:10:52,980 --> 00:10:56,970 have been replaced by my mock implementation here. 231 00:10:56,970 --> 00:10:59,490 When my component says setMin 232 00:10:59,490 --> 00:11:02,610 is actually gonna call this mock object 233 00:11:02,610 --> 00:11:04,620 is gonna call this mock function here 234 00:11:04,620 --> 00:11:07,710 and I can check, has that function been evoked? 235 00:11:07,710 --> 00:11:11,910 Did my component actually call this segment function 236 00:11:11,910 --> 00:11:15,723 when the user typed in a new value in the minimum text box? 237 00:11:16,830 --> 00:11:18,210 Well, that was quite tricky. 238 00:11:18,210 --> 00:11:20,250 Let's put it all together. 239 00:11:20,250 --> 00:11:23,310 In my test harness, I've got several tests 240 00:11:23,310 --> 00:11:25,080 they're all quite similar to each other, 241 00:11:25,080 --> 00:11:28,563 so I'll just focus on the first function, the first test. 242 00:11:29,490 --> 00:11:31,983 You can get all the tests, if you want to, here. 243 00:11:33,270 --> 00:11:36,210 I've got some dummy products, 244 00:11:36,210 --> 00:11:38,520 I've got something that happens after each test, 245 00:11:38,520 --> 00:11:40,980 I need to basically tidy up my mocks. 246 00:11:40,980 --> 00:11:44,190 I've got four tests which are all really, 247 00:11:44,190 --> 00:11:46,290 you know, evolutions of each other, 248 00:11:46,290 --> 00:11:47,670 we just need to look at the first one 249 00:11:47,670 --> 00:11:49,920 to understand what's going on. 250 00:11:49,920 --> 00:11:53,190 So test that the state was updated 251 00:11:53,190 --> 00:11:56,193 when the user entered a value in the minimum text box. 252 00:11:57,630 --> 00:11:59,580 That's what we got here. 253 00:11:59,580 --> 00:12:02,100 So remember, well let's actually do this 254 00:12:02,100 --> 00:12:03,390 from first principles then. 255 00:12:03,390 --> 00:12:07,080 So first of all, I'm setting up a dummy version 256 00:12:07,080 --> 00:12:08,433 of a callback function. 257 00:12:09,360 --> 00:12:11,980 That's a dummy version of the function 258 00:12:13,015 --> 00:12:15,390 that the component will hopefully invoke. 259 00:12:15,390 --> 00:12:16,773 Here's my component here, 260 00:12:17,970 --> 00:12:20,610 which will come into play in a moment. 261 00:12:20,610 --> 00:12:21,990 That's the first line. 262 00:12:21,990 --> 00:12:24,720 The second line, when I basically set up 263 00:12:24,720 --> 00:12:27,909 the dummy version of React.useState. 264 00:12:27,909 --> 00:12:30,600 So when my component calls React.useState, 265 00:12:30,600 --> 00:12:34,260 in fact, it's gonna be calling this dummy function instead 266 00:12:34,260 --> 00:12:36,630 and that's what I drew on the previous slide, 267 00:12:36,630 --> 00:12:39,363 a dummy version of React.useState, 268 00:12:40,200 --> 00:12:42,540 and when that function is invoked 269 00:12:42,540 --> 00:12:45,480 it will return a dummy set of values. 270 00:12:45,480 --> 00:12:48,600 It'll return an array. 271 00:12:48,600 --> 00:12:50,730 The first element is zero, 272 00:12:50,730 --> 00:12:52,530 like the value of minimum, 273 00:12:52,530 --> 00:12:54,000 and then the second parameter it says, 274 00:12:54,000 --> 00:12:58,500 oh, call this function, call the mock function. 275 00:12:58,500 --> 00:13:00,570 That's the function that will be invoked. 276 00:13:00,570 --> 00:13:01,590 That's what comes back. 277 00:13:01,590 --> 00:13:04,020 So in my application, let's see what happens. 278 00:13:04,020 --> 00:13:09,020 When I mount my product component with products 279 00:13:09,060 --> 00:13:12,210 I then simulate the user entering a value 280 00:13:12,210 --> 00:13:13,380 in the minimum text box, 281 00:13:13,380 --> 00:13:17,190 I'm simulating the user entering a value 282 00:13:17,190 --> 00:13:19,470 in the min text box, a change event, 283 00:13:19,470 --> 00:13:23,253 as if the user had entered 200 in the minimum text box. 284 00:13:24,540 --> 00:13:27,720 Well, if I just go back to the actual code, 285 00:13:27,720 --> 00:13:31,473 just to remind you, in my actual code for ProductList, 286 00:13:32,670 --> 00:13:35,400 if the user had entered the value 200 287 00:13:35,400 --> 00:13:36,963 in the minimum text box, 288 00:13:38,130 --> 00:13:39,973 it would've called onChangeMin, 289 00:13:41,340 --> 00:13:45,510 onChangeMin says, get the value, 200, 290 00:13:45,510 --> 00:13:48,480 and invoke the callback function. 291 00:13:48,480 --> 00:13:51,750 Well, that's the callback function that I've mocked 292 00:13:51,750 --> 00:13:55,020 so when I simulated the user entering a value 293 00:13:55,020 --> 00:13:58,140 in the text box, what I'm testing is I'm saying 294 00:13:58,140 --> 00:14:01,410 did it actually call the updated function 295 00:14:01,410 --> 00:14:02,703 with the value 200? 296 00:14:04,170 --> 00:14:08,217 So verify that my mock implementation 297 00:14:08,217 --> 00:14:11,010 of the updated function has been called 298 00:14:11,010 --> 00:14:12,273 with the value 200. 299 00:14:14,610 --> 00:14:17,790 I've got an important step to do as well, 300 00:14:17,790 --> 00:14:22,470 after each test, mock functions accumulate history 301 00:14:22,470 --> 00:14:24,990 about how many times they've been called, 302 00:14:24,990 --> 00:14:26,670 what values they've been called with, 303 00:14:26,670 --> 00:14:28,590 what parameters and such like. 304 00:14:28,590 --> 00:14:31,710 So it's pretty important that the end of each test 305 00:14:31,710 --> 00:14:36,090 that you clear any mock objects and reinstate the originals. 306 00:14:36,090 --> 00:14:39,150 So when you say jest.restoreAllMocks, 307 00:14:39,150 --> 00:14:42,180 it clears all information about 308 00:14:42,180 --> 00:14:45,510 how those mock functions were invoked, 309 00:14:45,510 --> 00:14:49,290 it forgets any implementation that you've installed 310 00:14:49,290 --> 00:14:51,780 for those mock functions and return values 311 00:14:51,780 --> 00:14:54,720 and it reinstates the original function. 312 00:14:54,720 --> 00:14:57,780 So after each test, I will reinstate 313 00:14:57,780 --> 00:15:01,110 the original React.useState function. 314 00:15:01,110 --> 00:15:03,000 What I'll then do in the next test 315 00:15:03,000 --> 00:15:06,270 is to mock it again with a fresh mock. 316 00:15:06,270 --> 00:15:08,490 So I've got three other tests 317 00:15:08,490 --> 00:15:10,830 that simulate the user clicking 318 00:15:10,830 --> 00:15:15,600 the minimum text box but with an empty value 319 00:15:15,600 --> 00:15:19,680 or the user entering a value in the maximum text box 320 00:15:19,680 --> 00:15:24,150 or the user having an empty maximum text box. 321 00:15:24,150 --> 00:15:26,460 Should we just have a look at the second one maybe? 322 00:15:26,460 --> 00:15:29,670 Just as a proof of concept and see what that does. 323 00:15:29,670 --> 00:15:31,980 Let's have a look. 324 00:15:31,980 --> 00:15:33,483 This is the second test. 325 00:15:34,350 --> 00:15:37,980 These two tests test the minimum text box 326 00:15:37,980 --> 00:15:42,300 and the last two tests test the maximum text box. 327 00:15:42,300 --> 00:15:44,340 They're pretty much the same idea 328 00:15:44,340 --> 00:15:45,990 so let's have a look at this one. 329 00:15:47,550 --> 00:15:50,130 Define a mock callback function 330 00:15:50,130 --> 00:15:51,570 that my component will invoke 331 00:15:51,570 --> 00:15:53,820 when it thinks it's set in the minimum price. 332 00:15:54,750 --> 00:15:58,440 Define a mock implementation for React.useState 333 00:15:58,440 --> 00:16:03,440 such that it will hook up my mock implementation of setMin. 334 00:16:04,110 --> 00:16:05,760 That's the function my component 335 00:16:05,760 --> 00:16:07,173 will actually be invoking. 336 00:16:09,325 --> 00:16:13,020 So mount my component, ProductList, 337 00:16:13,020 --> 00:16:16,290 simulate entry into the minimum text box, 338 00:16:16,290 --> 00:16:19,530 simulating the user having an empty text box. 339 00:16:19,530 --> 00:16:21,450 Now that's an interesting thing. 340 00:16:21,450 --> 00:16:25,020 What value should it adopt for the minimum 341 00:16:25,020 --> 00:16:28,410 if the text box is empty and I'm saying 342 00:16:28,410 --> 00:16:31,320 ideally it should say it should call back 343 00:16:31,320 --> 00:16:33,993 into React and set the minimum price to be zero. 344 00:16:35,070 --> 00:16:37,980 So if the user has an empty text box for minimum 345 00:16:37,980 --> 00:16:40,800 then that's as if the value was zero. 346 00:16:40,800 --> 00:16:44,670 It should tell React to use the minimum value of zero. 347 00:16:44,670 --> 00:16:46,170 But my code actually does do that, 348 00:16:46,170 --> 00:16:47,970 if you remember, I was quite careful 349 00:16:48,900 --> 00:16:51,720 when I grab the minimum value from the user 350 00:16:51,720 --> 00:16:53,430 if the text box was empty, 351 00:16:53,430 --> 00:16:55,680 it substitutes the value zero in 352 00:16:55,680 --> 00:16:58,053 and it passes zero into setMin. 353 00:16:58,950 --> 00:17:01,020 Okay, well, that's what I've just verified. 354 00:17:01,020 --> 00:17:02,580 If the text box, 355 00:17:02,580 --> 00:17:06,450 if the user enters an empty value in the text box, 356 00:17:06,450 --> 00:17:09,210 an empty value in the text box, 357 00:17:09,210 --> 00:17:12,303 then the minimum price should be set to zero. 358 00:17:13,140 --> 00:17:15,390 And in a similar kind of way 359 00:17:15,390 --> 00:17:17,160 let's have a look at what happens in the case 360 00:17:17,160 --> 00:17:20,310 where it's an empty maximum box here. 361 00:17:20,310 --> 00:17:24,600 So register a mock version of a callback 362 00:17:24,600 --> 00:17:27,180 to update the maximum price. 363 00:17:27,180 --> 00:17:29,500 Mock the React.useState function 364 00:17:30,900 --> 00:17:33,120 such that it returns the value zero 365 00:17:33,120 --> 00:17:35,490 and it says, call this function 366 00:17:35,490 --> 00:17:37,983 if you want to change the value of the maximum. 367 00:17:38,940 --> 00:17:41,310 Mount the component, ProductList, 368 00:17:41,310 --> 00:17:44,730 simulate the user entering the value into the max text box, 369 00:17:44,730 --> 00:17:46,980 an empty text box. 370 00:17:46,980 --> 00:17:50,880 What value should it then set for the maximum price 371 00:17:50,880 --> 00:17:52,320 if the maximum price is empty? 372 00:17:52,320 --> 00:17:56,430 Well, what did it do if the maximum text box is empty? 373 00:17:56,430 --> 00:17:59,700 What does it use for the maximum price? 374 00:17:59,700 --> 00:18:02,010 Well, of course, in the real code, 375 00:18:02,010 --> 00:18:04,920 the value that it uses when it tries to get the value 376 00:18:04,920 --> 00:18:06,330 for the maximum price, 377 00:18:06,330 --> 00:18:09,270 the value it uses by default, if it's empty, 378 00:18:09,270 --> 00:18:13,290 is defaultMax, defaultMax is a million. 379 00:18:13,290 --> 00:18:15,210 So if the text box is empty 380 00:18:15,210 --> 00:18:18,090 my code should have called the setMax function 381 00:18:18,090 --> 00:18:20,040 with a value of a million. 382 00:18:20,040 --> 00:18:21,033 Did it do that? 383 00:18:22,800 --> 00:18:23,733 Let's have a look. 384 00:18:25,620 --> 00:18:28,593 If the maximum text box is empty, 385 00:18:29,460 --> 00:18:33,270 then it should have called the setMax function 386 00:18:33,270 --> 00:18:34,670 with the value of a million. 387 00:18:35,760 --> 00:18:38,497 So really what I'm doing is I'm checking 388 00:18:38,497 --> 00:18:42,330 is the correct default value used for the maximum 389 00:18:42,330 --> 00:18:43,890 in the case where the text box was empty. 390 00:18:43,890 --> 00:18:47,100 That's an interesting important test to have, 391 00:18:47,100 --> 00:18:48,390 something that matters, you know? 392 00:18:48,390 --> 00:18:49,890 If the text box is empty 393 00:18:49,890 --> 00:18:52,470 we need to know what to do in that situation, 394 00:18:52,470 --> 00:18:55,260 simulate a value of a million. 395 00:18:55,260 --> 00:18:57,060 So, all what we need to do. 396 00:18:57,060 --> 00:18:58,710 There was a lot of detail in there, 397 00:18:58,710 --> 00:19:00,840 but we just need to run the tests. 398 00:19:00,840 --> 00:19:02,610 There were four tests altogether 399 00:19:02,610 --> 00:19:05,580 and hey presto, they all worked. 400 00:19:05,580 --> 00:19:08,430 All right, so have a look to that again. 401 00:19:08,430 --> 00:19:09,810 I think the main point is 402 00:19:09,810 --> 00:19:12,600 we're mocking the useState function 403 00:19:12,600 --> 00:19:15,930 and we're mocking the callback function to be invoked 404 00:19:15,930 --> 00:19:18,600 when my component tries to change the value 405 00:19:18,600 --> 00:19:19,980 and we can then check 406 00:19:19,980 --> 00:19:22,050 that the updated function was invoked 407 00:19:22,050 --> 00:19:24,443 when it should have been with the correct values.