1 00:00:00,470 --> 00:00:02,460 Now that we've got our home page all set up, 2 00:00:02,460 --> 00:00:06,030 it quickly became evident that we have a bunch of repeated elements. 3 00:00:06,030 --> 00:00:07,710 Well, mainly those invitees. 4 00:00:07,710 --> 00:00:11,600 All of them have very similar properties and functionality. 5 00:00:11,600 --> 00:00:16,059 Now, we could write methods on our main page object, but that would require us to 6 00:00:16,059 --> 00:00:19,812 continually pass the name of the invitee to each of our new methods. 7 00:00:19,812 --> 00:00:22,280 There's probably a better API that we could design. 8 00:00:23,640 --> 00:00:26,600 It's important to remember that just like how you take your time to 9 00:00:26,600 --> 00:00:30,880 design a software, you should also do the same with your automation and test code. 10 00:00:30,880 --> 00:00:35,245 You should always follow best practices and create clean, understandable APIs. 11 00:00:35,245 --> 00:00:38,504 You want other people to be able to not only read your code, but 12 00:00:38,504 --> 00:00:41,240 also being encourage to reuse it. 13 00:00:41,240 --> 00:00:44,790 Remember, even though this pattern of abstracting away knowledge 14 00:00:44,790 --> 00:00:47,980 of the structure of a page is called page object, 15 00:00:47,980 --> 00:00:51,150 the classes you create don't need to be entire pages. 16 00:00:51,150 --> 00:00:53,200 They can be sub-pages as well. 17 00:00:53,200 --> 00:00:55,400 Let's model our invitee as a sub-page. 18 00:00:56,720 --> 00:00:59,659 Okay, so first things first, 19 00:00:59,659 --> 00:01:05,320 let's think about how we can get a handle on each of these little invitee blocks. 20 00:01:05,320 --> 00:01:08,962 So we've kinda done that already, haven't we, with our locator function here, right, 21 00:01:08,962 --> 00:01:10,300 this removeButtonForInvitee. 22 00:01:10,300 --> 00:01:14,120 It basically just goes and it only gets the button, though. 23 00:01:14,120 --> 00:01:17,016 So why don't we do one where we get the invitee by name. 24 00:01:17,016 --> 00:01:19,094 I'm gonna leave that one there for reference, and 25 00:01:19,094 --> 00:01:20,455 actually I'll duplicate that. 26 00:01:20,455 --> 00:01:24,175 So make a new one of those. 27 00:01:24,175 --> 00:01:27,285 And what we want is we want invitee, 28 00:01:27,285 --> 00:01:30,090 I'm gonna get ahold of the invitee element there. 29 00:01:30,090 --> 00:01:34,467 So we'll say inviteeByName. 30 00:01:34,467 --> 00:01:35,667 And just to be clear, 31 00:01:35,667 --> 00:01:39,811 we'll change our parameter from being called invitee to be called name. 32 00:01:39,811 --> 00:01:43,896 And we'll pass that in here, to name. 33 00:01:43,896 --> 00:01:46,920 And instead of going to the button, let's just go to the parent there. 34 00:01:46,920 --> 00:01:49,080 So that will get that li, won't it? 35 00:01:49,080 --> 00:01:50,290 That li is this here. 36 00:01:51,940 --> 00:01:54,266 We go ahead and we inspect this here. 37 00:02:00,304 --> 00:02:04,270 That's this li, this is the parent that we're gonna get from that. 38 00:02:04,270 --> 00:02:06,080 Okay, awesome, and 39 00:02:06,080 --> 00:02:10,456 then let's give our page a way to get a handle on those elements. 40 00:02:10,456 --> 00:02:14,310 So I kinda like the way that Selenium API works when you call find element. 41 00:02:14,310 --> 00:02:17,805 So why don't we add new method to our homepage. 42 00:02:17,805 --> 00:02:20,640 And we we'll kinda follow the same structure, this is pretty common. 43 00:02:20,640 --> 00:02:28,241 So we can say findInviteeByName. 44 00:02:28,241 --> 00:02:30,503 And that takes a name. 45 00:02:30,503 --> 00:02:37,493 And then what we'll do is we'll get an element, 46 00:02:37,493 --> 00:02:41,790 and we will do this.driver. 47 00:02:41,790 --> 00:02:46,063 We'll say findElement, and we will pass in 48 00:02:46,063 --> 00:02:51,961 this.locators.inviteeByName, which we just created. 49 00:02:51,961 --> 00:02:53,800 And we'll pass in that name, awesome. 50 00:02:53,800 --> 00:02:55,197 So then we have the element. 51 00:02:55,197 --> 00:03:00,616 And then we'll say, return, so we wanna return a new Invitee. 52 00:03:00,616 --> 00:03:03,100 And we haven't built that yet, so let's be careful. 53 00:03:03,100 --> 00:03:06,810 So we're gonna pass in the element to that, cool. 54 00:03:06,810 --> 00:03:11,560 So what we'll do, Keep that function there. 55 00:03:11,560 --> 00:03:14,140 And we need to define what a new Invitee looks like. 56 00:03:14,140 --> 00:03:15,690 So we'll just build one right here. 57 00:03:15,690 --> 00:03:21,270 We'll say class Invitee, and we know that it's gonna take an element. 58 00:03:21,270 --> 00:03:23,930 So we need to pass that into the constructor, right? 59 00:03:23,930 --> 00:03:31,380 So we'll say, constructor, we'll pass in an element. 60 00:03:31,380 --> 00:03:34,340 And then we'll just store a reference to it in the instance, right? 61 00:03:34,340 --> 00:03:38,770 So when this is called it will have a reference to that element, awesome. 62 00:03:38,770 --> 00:03:42,670 So this is much like we did here with the constructor when we passed in the driver. 63 00:03:42,670 --> 00:03:47,232 But this is going to be built and it's gonna be given an element. 64 00:03:47,232 --> 00:03:49,880 So this is where things probably differ a bit depending on your 65 00:03:49,880 --> 00:03:50,620 programming language. 66 00:03:52,140 --> 00:03:55,610 Basically we only really want our HomePage class here 67 00:03:55,610 --> 00:03:58,770 to create these Invitees, right? 68 00:03:58,770 --> 00:04:03,728 And we want to convey to users of our API that our invitee class shouldn't be 69 00:04:03,728 --> 00:04:04,445 created. 70 00:04:04,445 --> 00:04:08,240 Now maybe in your language you would mark a private or protected class. 71 00:04:08,240 --> 00:04:11,460 Or maybe you would tweak the accessibility of the constructor. 72 00:04:11,460 --> 00:04:15,890 Over here in JavaScript Landia, we simply won't add it to our module exports. 73 00:04:15,890 --> 00:04:18,030 So nobody can see it, which is more or 74 00:04:18,030 --> 00:04:21,690 less a private class since you can't import it elsewhere. 75 00:04:21,690 --> 00:04:24,950 Great, so now that we have our specific invitee class, 76 00:04:24,950 --> 00:04:29,030 we can now refactor the removeInvitee bit, right? 77 00:04:29,030 --> 00:04:32,400 So we have this removeInvitee bit that we had. 78 00:04:32,400 --> 00:04:37,270 So let's take a look at what this locator looks like. 79 00:04:37,270 --> 00:04:39,290 So if I press Command here I can click it. 80 00:04:40,870 --> 00:04:43,032 So let's go ahead and let's grab this off. 81 00:04:46,121 --> 00:04:49,320 And let's go and let's add a new locators to our invitee. 82 00:04:49,320 --> 00:04:50,992 So it'll be specific to this class. 83 00:04:56,935 --> 00:04:58,795 So let's call this removeButton, right, 84 00:04:58,795 --> 00:05:01,750 cuz that's the Remove button in that little block there. 85 00:05:01,750 --> 00:05:04,100 Let's take a look at what it was, it was just button[last()]. 86 00:05:05,690 --> 00:05:10,083 So, you know what, let's switch what our locator was there. 87 00:05:10,083 --> 00:05:14,276 So we'll say removeButton is a By.css. 88 00:05:14,276 --> 00:05:17,345 And we'll say, button:last-child, right? 89 00:05:17,345 --> 00:05:21,278 Cuz it's is gonna search within element is what we'll do. 90 00:05:21,278 --> 00:05:24,750 So now that we have that removeButton we can use it in an element. 91 00:05:24,750 --> 00:05:28,956 And so, instead of saying remove invitee, we can just say remove, right? 92 00:05:28,956 --> 00:05:34,044 Cuz you'll have a hold of the Invitee and we'll just call remove on it. 93 00:05:34,044 --> 00:05:37,170 And we'll say this.element, right? 94 00:05:37,170 --> 00:05:40,180 Instead of using the driver, we're gonna search from within that element. 95 00:05:40,180 --> 00:05:47,416 We'll say findElement and then we'll say this.locators.removeButton. 96 00:05:47,416 --> 00:05:52,697 And then we wanna click, beautiful. 97 00:05:52,697 --> 00:05:56,208 Okay, so let's get rid of this 98 00:05:56,208 --> 00:06:01,780 removeInvitee here cuz now that is not the responsibility anymore. 99 00:06:01,780 --> 00:06:03,594 So, let's see. 100 00:06:06,813 --> 00:06:10,340 So we've got this invitee form and we're gonna do findInviteeByName. 101 00:06:10,340 --> 00:06:13,940 So it's usage is gonna look a little bit different in index.js. 102 00:06:13,940 --> 00:06:17,173 So here, before what we we're doing, we were removing Shadd. 103 00:06:17,173 --> 00:06:24,437 We're gonna get rid of this, and we'll say homePage.findInviteeByName. 104 00:06:24,437 --> 00:06:28,110 And we're gonna pass in David Riesz. 105 00:06:30,330 --> 00:06:32,607 And then we're gonna call, that's what's wrong. 106 00:06:36,097 --> 00:06:42,230 You gotta put the dot at the front of each one of these lines, .remove, there we go. 107 00:06:43,610 --> 00:06:46,640 So first, we're gonna find it and then we're gonna method chain and 108 00:06:46,640 --> 00:06:49,034 do a remove, sorry, David. 109 00:06:50,295 --> 00:06:52,674 Now, let's get insider of here. 110 00:06:52,674 --> 00:06:55,835 Now that we've got this little invitee, I feel like we're on a roll. 111 00:06:55,835 --> 00:06:58,625 Let's get this little checkbox working, okay? 112 00:06:58,625 --> 00:07:02,621 So let's add to our invitee sub-page. 113 00:07:02,621 --> 00:07:05,935 Let's go over to our invitee sub page. 114 00:07:05,935 --> 00:07:11,670 And let's add the confirmedCheckbox. 115 00:07:11,670 --> 00:07:14,710 Now, these finders start getting a lot easier, right? 116 00:07:14,710 --> 00:07:17,150 So is there anymore, there's only that one, right? 117 00:07:17,150 --> 00:07:18,460 There's only one checkbox on there. 118 00:07:19,890 --> 00:07:25,030 And it's, let's see, it's an input type of checkbox. 119 00:07:25,030 --> 00:07:25,770 So, let's just do that. 120 00:07:25,770 --> 00:07:30,063 Let say, By.css, and we'll do, 121 00:07:30,063 --> 00:07:34,250 input [type='checkbox']. 122 00:07:34,250 --> 00:07:37,280 And I use the single quotes there because they were double quotes. 123 00:07:37,280 --> 00:07:41,196 And I'm gonna actually fix this, cuz I accidentally typed single quotes there. 124 00:07:45,215 --> 00:07:48,572 Cool, so we now have a confirmedCheckbox. 125 00:07:48,572 --> 00:07:52,084 That it's complaining about cuz there's no comma, there we go. 126 00:07:52,084 --> 00:07:54,850 And then let's go ahead and let's use it. 127 00:07:54,850 --> 00:08:01,817 So if you get ahold of an invitee, you can toggleConfirmation, right? 128 00:08:01,817 --> 00:08:07,038 So what we'll do is we'll say this.element, findElement, 129 00:08:07,038 --> 00:08:13,450 search within there, and we'll do this.locators.confirmedCheckbox. 130 00:08:13,450 --> 00:08:16,113 Awesome, and then we'll do a .click. 131 00:08:16,113 --> 00:08:18,740 So that will check that box for us from inside. 132 00:08:19,800 --> 00:08:22,190 And then in index.js, let's use it. 133 00:08:24,100 --> 00:08:26,235 So let's see, so we'll do homePage. 134 00:08:28,776 --> 00:08:35,660 We'll do findInviteeByName and let's see, if this is a treehouse party, 135 00:08:35,660 --> 00:08:41,010 if anybody's gonna be there, I know that it's gonna be Jennifer Nordell. 136 00:08:41,010 --> 00:08:44,028 She's got something like 100,000 points or something. 137 00:08:44,028 --> 00:08:45,420 You've probably met her in the forums. 138 00:08:45,420 --> 00:08:47,670 She's an amazing moderator. 139 00:08:47,670 --> 00:08:49,790 So let's do that, she's gonna come, for sure she's gonna come. 140 00:08:49,790 --> 00:08:52,940 So we'll toggle her confirmation true. 141 00:08:52,940 --> 00:08:55,760 And thanks for all your help and dedication, Jennifer. 142 00:08:55,760 --> 00:08:59,433 And thanks for RSVPing so promptly through this app. 143 00:08:59,433 --> 00:09:01,060 So let's do it, let's give it a go. 144 00:09:01,060 --> 00:09:04,880 So I'm gonna close that existing one that I have. 145 00:09:04,880 --> 00:09:09,260 And let's open it up again, and here we go. 146 00:09:09,260 --> 00:09:13,060 She's confirmed, and we click hide those that aren't there, so there's Jennifer. 147 00:09:14,100 --> 00:09:17,140 And let's make sure that David's gone. 148 00:09:17,140 --> 00:09:18,430 Yeah so we had to kick him out of that party. 149 00:09:18,430 --> 00:09:21,080 He just kept talking about Java and algorithms. 150 00:09:21,080 --> 00:09:23,849 We just [LAUGH] had to kick him out. 151 00:09:23,849 --> 00:09:27,700 Okay, our new API is feeling pretty good. 152 00:09:27,700 --> 00:09:30,510 Now I could imagine how you'd do the rest of these actions, right, 153 00:09:30,510 --> 00:09:32,080 the rest of these ones that are left. 154 00:09:32,080 --> 00:09:34,970 I could kinda see how you'd do edit, right? 155 00:09:34,970 --> 00:09:36,910 Cuz edit comes in and you can change the name. 156 00:09:37,970 --> 00:09:39,734 Actually, that's a good idea. 157 00:09:39,734 --> 00:09:44,120 If you wanna challenge yourself, go ahead and give changing this name a try. 158 00:09:44,120 --> 00:09:47,170 Now I've dropped how I did it in the teacher's notes, no cheating. 159 00:09:49,280 --> 00:09:54,278 One thing that I noticed here, is that this page is a little weird, right? 160 00:09:54,278 --> 00:09:57,220 The line up of these buttons is a little strange. 161 00:09:57,220 --> 00:10:01,805 I was thinking that maybe I should share this in a screenshot to my designer. 162 00:10:01,805 --> 00:10:04,570 And I thought well, maybe I can make this screenshot myself. 163 00:10:04,570 --> 00:10:07,080 But get this, Selenium can do it for you. 164 00:10:07,080 --> 00:10:10,970 But first, we're gonna need to be able to get access to our file system. 165 00:10:10,970 --> 00:10:15,760 So that is a node thing called fs for file system. 166 00:10:15,760 --> 00:10:17,494 So we'll require fs. 167 00:10:17,494 --> 00:10:21,510 And what we'll do is we'll make Selenium take the screenshot. 168 00:10:21,510 --> 00:10:24,570 So we'll go down here to the bottom, half of this is all done. 169 00:10:24,570 --> 00:10:29,300 Let's not toggle this off, we wanna be able to show everybody on there. 170 00:10:29,300 --> 00:10:34,360 So we'll say, drive.takeScreenshot, okay? 171 00:10:34,360 --> 00:10:37,520 And that's thenable, that gets returned, right? 172 00:10:37,520 --> 00:10:41,290 So, and we'll do then and 173 00:10:41,290 --> 00:10:46,860 that expects a callback that takes in an image and an err if it didn't work, okay? 174 00:10:46,860 --> 00:10:51,700 So our function will have an image and it's kind of a blob there. 175 00:10:51,700 --> 00:10:58,010 So we'll say fs.writeFile and we'll just call this weird-layout. 176 00:10:58,010 --> 00:10:59,199 Those buttons aren't lining up. 177 00:10:59,199 --> 00:11:04,875 We wanna show our designer, she loves it when we send screenshots. 178 00:11:04,875 --> 00:11:06,200 Because that's the nice thing about this, right? 179 00:11:06,200 --> 00:11:09,300 You could set this up, and because those names were a little bit longer, 180 00:11:09,300 --> 00:11:11,280 we saw that the thing was breaking a little bit. 181 00:11:11,280 --> 00:11:12,970 So let's send this over to her so she can see it. 182 00:11:12,970 --> 00:11:18,930 And finally, it takes an error, a method that takes an error. 183 00:11:18,930 --> 00:11:21,510 So we'll just drop a new function here that says err. 184 00:11:21,510 --> 00:11:26,990 And we'll log out to the console if there is one, log in that error out. 185 00:11:28,240 --> 00:11:30,070 Okay, so there we go. 186 00:11:30,070 --> 00:11:32,422 So it's complaining about something. 187 00:11:32,422 --> 00:11:35,353 I forgot this and this, there we go. 188 00:11:41,038 --> 00:11:43,022 That's not quite lining up. 189 00:11:43,022 --> 00:11:48,968 I have an extra, so that closes the then, this closes the function. 190 00:11:48,968 --> 00:11:51,380 And I've got, this closes the right file, cool. 191 00:11:52,760 --> 00:11:57,662 All right, so what will happen is it will write out this weird-layout. 192 00:11:57,662 --> 00:11:59,260 And it will push the image in there. 193 00:11:59,260 --> 00:12:02,310 So let's do that, let's go and drop this here. 194 00:12:02,310 --> 00:12:05,750 Let's run it one more time, and then we'll, should, when it all said and done, 195 00:12:05,750 --> 00:12:07,300 we should see a new file pop in here. 196 00:12:08,670 --> 00:12:11,003 Cool, so there's this weird-layout.png. 197 00:12:11,003 --> 00:12:14,310 And look at that, we can just show them right here. 198 00:12:14,310 --> 00:12:16,950 Show our designer that these buttons aren't lining up when you have 199 00:12:16,950 --> 00:12:17,500 longer names. 200 00:12:17,500 --> 00:12:21,400 This Gonzalo Torres del Fierro has broken this here. 201 00:12:21,400 --> 00:12:24,650 And I'm sure that this is not the first time that he's witnessed this, 202 00:12:24,650 --> 00:12:25,970 right Gonzalo? 203 00:12:25,970 --> 00:12:30,070 So there are actually quite a bit of things that Selenium can do at the browser 204 00:12:30,070 --> 00:12:30,750 like this. 205 00:12:30,750 --> 00:12:33,230 Now why don't you take a quick break and then come back and 206 00:12:33,230 --> 00:12:36,140 get ready to practice your new skills and pick up a few more.