1 00:00:00,210 --> 00:00:04,350 Using Selenium WebDriver together with a testing framework lets you write tests 2 00:00:04,350 --> 00:00:06,380 once and keep using them forever. 3 00:00:06,380 --> 00:00:09,650 Old tests can be run automatically against new versions of your app 4 00:00:09,650 --> 00:00:12,660 to ensure that no new bugs are introduced. 5 00:00:12,660 --> 00:00:16,650 In JavaScript, the most popular testing frameworks are Jasmine and Mocha. 6 00:00:16,650 --> 00:00:18,660 We'll be using Mocha for this course. 7 00:00:18,660 --> 00:00:20,450 If you're not familiar with Mocha already, 8 00:00:20,450 --> 00:00:22,840 we have some resources that can get you up to speed. 9 00:00:22,840 --> 00:00:24,990 See the Teacher's Notes. 10 00:00:24,990 --> 00:00:27,000 We're going to start by writing some tests for 11 00:00:27,000 --> 00:00:30,790 our RSVP app that we saw in a previous course. 12 00:00:30,790 --> 00:00:32,660 So let's create our first Mocha test. 13 00:00:32,660 --> 00:00:37,360 First, I'm going to create a directory named test, 14 00:00:37,360 --> 00:00:39,170 that'll hold all of our Mocha tests. 15 00:00:40,470 --> 00:00:43,100 Then within that, I'm going to create a JavaScript file 16 00:00:44,190 --> 00:00:49,140 named Invitees.js. 17 00:00:49,140 --> 00:00:52,650 We'll start by importing the Selenium WebDriver library. 18 00:00:52,650 --> 00:00:57,216 I'm going to assign several values that it returns to a series of constants. 19 00:00:59,413 --> 00:01:04,120 Let me show you what's going on here in the node read, evaluate, print, loop. 20 00:01:04,120 --> 00:01:07,498 So I'm gonna run node here in our terminal, and 21 00:01:07,498 --> 00:01:11,725 I'm going to run require ("selenium-webdriver"). 22 00:01:16,385 --> 00:01:21,335 And you can see that it returns a JavaScript objects with a whole bunch of 23 00:01:21,335 --> 00:01:23,700 subsections here. 24 00:01:23,700 --> 00:01:28,310 We have a browser here under this key, we have By, 25 00:01:28,310 --> 00:01:32,280 which is used for locating elements within the page. 26 00:01:32,280 --> 00:01:37,540 We have various keystrokes that the user can type at their keyboard. 27 00:01:39,040 --> 00:01:42,680 And we have until, which is used for waiting for 28 00:01:42,680 --> 00:01:44,710 certain page elements to appear. 29 00:01:44,710 --> 00:01:47,700 We'll be explaining all of these components further later in the course. 30 00:01:47,700 --> 00:01:48,320 But for right now, 31 00:01:48,320 --> 00:01:52,260 I'm just going to assign them to constants here in our JavaScript code. 32 00:01:53,730 --> 00:01:55,878 So let me exit out of the node ripple here. 33 00:01:58,672 --> 00:02:01,282 Selenium also includes some libraries that are used 34 00:02:01,282 --> 00:02:03,720 to integrate with the Mocha testing framework. 35 00:02:03,720 --> 00:02:04,826 I'll import those now. 36 00:02:07,848 --> 00:02:11,531 We're also going to need a library that's part of Node.js itself, 37 00:02:11,531 --> 00:02:15,930 which lets us assert that conditions of our tests are as they're supposed to be. 38 00:02:15,930 --> 00:02:20,230 So I'm going to require the assert library and assign that to another constant. 39 00:02:20,230 --> 00:02:21,980 We'll see how to use that in just a little bit. 40 00:02:23,070 --> 00:02:24,888 Now we'll call the suite method, 41 00:02:24,888 --> 00:02:28,347 which we imported from our Selenium WebDriver testing library. 42 00:02:30,257 --> 00:02:35,190 And a call to suite expects a function callback, which I'll define here. 43 00:02:35,190 --> 00:02:37,250 And that functions going to receive one parameter, 44 00:02:37,250 --> 00:02:38,870 which is our testing environment. 45 00:02:38,870 --> 00:02:42,670 This is going to set up various aspects of our test for us. 46 00:02:42,670 --> 00:02:46,570 We'll see how to use that test environment here in just a little bit. 47 00:02:46,570 --> 00:02:50,150 Out test suite expects us to describe various aspects of our app. 48 00:02:50,150 --> 00:02:52,450 We do that by calling the describe method. 49 00:02:53,660 --> 00:02:57,420 We need to provide a string, which shows which aspect of our app we're describing. 50 00:02:57,420 --> 00:03:00,410 So I'm going to be describing the RSVP site here. 51 00:03:01,940 --> 00:03:04,120 And describe also takes a callback function, 52 00:03:04,120 --> 00:03:06,170 which is going to contain all of our tests. 53 00:03:06,170 --> 00:03:11,350 So I'll define function, an anonymous one, has no parameters. 54 00:03:13,090 --> 00:03:16,680 Now within this described function, we're going to write various tests 55 00:03:16,680 --> 00:03:20,240 describing what the thing we're testing is going to do. 56 00:03:20,240 --> 00:03:24,350 We've said that we are describing the RSVP site up here, and 57 00:03:24,350 --> 00:03:25,840 now we call the it method. 58 00:03:25,840 --> 00:03:29,870 We are saying things that it, the RSVP site, should do. 59 00:03:29,870 --> 00:03:34,338 So the RSVP site, among other things, should have an Invitee list. 60 00:03:36,478 --> 00:03:38,310 So I'll provide that in a string here. 61 00:03:39,540 --> 00:03:40,750 And now we need to provide yet 62 00:03:40,750 --> 00:03:43,970 another function callback with our actual test code. 63 00:03:43,970 --> 00:03:46,628 It's an anonymous function, has no parameters. 64 00:03:48,646 --> 00:03:51,520 And here's where we're going to write our actual test code. 65 00:03:51,520 --> 00:03:57,910 We do that by called assert method with various assertions that we want to write. 66 00:03:57,910 --> 00:04:01,270 If we pass a true value to assert, then our tests will pass. 67 00:04:01,270 --> 00:04:04,590 If we pass a false value, then our tests will fail. 68 00:04:04,590 --> 00:04:07,320 To demonstrate, let me just do a simple equality check here. 69 00:04:07,320 --> 00:04:11,450 We'll check whether the number 1 is equal to the number 2, 70 00:04:11,450 --> 00:04:13,840 which obviously is going to return false. 71 00:04:13,840 --> 00:04:14,911 Let's save that. 72 00:04:14,911 --> 00:04:20,620 And now we can go to our terminal and run our test by running the Mocha executable. 73 00:04:22,350 --> 00:04:26,240 And we can see here that the thing we're testing is the RSVP site, and 74 00:04:26,240 --> 00:04:29,890 the particular test is whether it has an invitee list. 75 00:04:29,890 --> 00:04:32,770 Well, we're not actually testing the site itself yet, 76 00:04:32,770 --> 00:04:35,980 we're just testing whether the number 1 equals the number 2. 77 00:04:35,980 --> 00:04:39,640 Obviously, that test fails because 1 does not equal 2. 78 00:04:39,640 --> 00:04:41,410 If we were to modify this so 79 00:04:41,410 --> 00:04:46,590 that we were testing something like does the number 1 equal the number 1. 80 00:04:46,590 --> 00:04:48,570 And if we were to rerun that, 81 00:04:48,570 --> 00:04:51,990 our test would pass because it returns a true value. 82 00:04:51,990 --> 00:04:54,660 Notice, by the way, that Mocha is running the test suite 83 00:04:54,660 --> 00:04:57,730 once with the Chrome browser, and again with the Firefox browser. 84 00:04:59,310 --> 00:05:02,830 Because we're using the suite function from the Selenium WebDriver testing 85 00:05:02,830 --> 00:05:06,290 package to wrap our tests, it'll automatically run those tests for 86 00:05:06,290 --> 00:05:08,880 each browser driver you have installed on your system. 87 00:05:09,990 --> 00:05:13,730 So now that we know how Mocha tests work, let's add some code to actually get 88 00:05:13,730 --> 00:05:16,840 the page, using Selenium WebDriver, and run a test against it. 89 00:05:18,000 --> 00:05:22,160 This version of the site has an unordered list element with an ID of invitedList, 90 00:05:22,160 --> 00:05:24,800 which we populate using an AJAX request. 91 00:05:24,800 --> 00:05:26,730 Let me inspect that real quick to show you the code. 92 00:05:27,990 --> 00:05:33,030 And here we can see our unordered list with our various list items, 93 00:05:33,030 --> 00:05:34,420 including our invitees. 94 00:05:35,840 --> 00:05:39,510 Let's add a test to ensure that the invited list element is present to alert 95 00:05:39,510 --> 00:05:43,520 us if we accidentally remove the element later and break our code. 96 00:05:43,520 --> 00:05:45,930 I'm going to show you how to write these tests two ways. 97 00:05:45,930 --> 00:05:49,560 The way I show you in this video is going to make it look really complicated, but 98 00:05:49,560 --> 00:05:51,940 I'll show you what's going on behind the scenes. 99 00:05:51,940 --> 00:05:52,640 In the next video, 100 00:05:52,640 --> 00:05:56,400 I'll show you some simpler looking code that does the same thing. 101 00:05:56,400 --> 00:05:59,380 So first we're going to need to know what URL to connect to, 102 00:05:59,380 --> 00:06:01,980 I'll just copy that out off my web browser. 103 00:06:01,980 --> 00:06:08,460 And I'll say const url =, and that URL that I copied. 104 00:06:08,460 --> 00:06:11,240 We'll have this URL in the Teacher's Notes. 105 00:06:11,240 --> 00:06:15,390 By the way, we set up this sample app on a public web server for your convenience. 106 00:06:15,390 --> 00:06:18,570 But when you're testing your own apps, you'll probably want to install it on 107 00:06:18,570 --> 00:06:20,830 the same computer where you're running your tests. 108 00:06:20,830 --> 00:06:23,130 That way you can connect a local host, and 109 00:06:23,130 --> 00:06:26,730 not have your tests slowed down by network delays. 110 00:06:26,730 --> 00:06:30,830 Okay, I'm going to delete this temporary demonstration code here, and 111 00:06:30,830 --> 00:06:35,690 let's replace it with codes that actually connect to the sample site. 112 00:06:35,690 --> 00:06:38,220 First up, I need the build a web driver object. 113 00:06:38,220 --> 00:06:41,950 I can do that because we're using the special suite function in 114 00:06:41,950 --> 00:06:42,920 a particular way. 115 00:06:42,920 --> 00:06:48,500 I can call the environment object that was passed to our test suite, and then 116 00:06:48,500 --> 00:06:54,950 that has a builder method available on it, which will return a driver builder object. 117 00:06:54,950 --> 00:06:59,210 And I can tell that object to build a new driver. 118 00:07:00,360 --> 00:07:03,900 Now, when we call build, we won't actually get the driver back right away. 119 00:07:03,900 --> 00:07:07,380 Instead we get a promise that we'll eventually get a driver. 120 00:07:07,380 --> 00:07:10,440 We need to call then on this promise. 121 00:07:10,440 --> 00:07:13,774 And we'll pass then a callback function that will be called when the driver is 122 00:07:13,774 --> 00:07:15,160 available. 123 00:07:15,160 --> 00:07:17,820 This uses JavaScript's arrow function syntax. 124 00:07:17,820 --> 00:07:20,910 If you're not familiar with this notation, see the Teacher's Notes. 125 00:07:22,150 --> 00:07:26,086 So this callback will receive the driver object as a parameter. 126 00:07:29,309 --> 00:07:32,990 Then within this callback function, we can actually use the driver object. 127 00:07:32,990 --> 00:07:36,800 So I'm going to say driver.get, and 128 00:07:36,800 --> 00:07:40,130 I'll give it the URL that I want it to retrieve. 129 00:07:40,130 --> 00:07:44,110 Again, get is going to return a promise that we need to call then on. 130 00:07:44,110 --> 00:07:49,110 We pass then another function, That's going to be 131 00:07:49,110 --> 00:07:51,490 called once the page is retrieved. 132 00:07:51,490 --> 00:07:57,106 So I'm going to find all the elements, And 133 00:07:57,106 --> 00:08:01,370 I'll use a locator, the ID locator. 134 00:08:01,370 --> 00:08:03,870 I'll have that look for an ID of invited list. 135 00:08:06,699 --> 00:08:09,720 FindElements is going to return yet another promise. 136 00:08:09,720 --> 00:08:13,400 When the list of matching elements is found, we'll test that it's not empty. 137 00:08:13,400 --> 00:08:19,280 So we'll call then on the promise, and we'll say that callback 138 00:08:19,280 --> 00:08:24,960 is going to receive the list of elements that were found as a perimeter. 139 00:08:24,960 --> 00:08:30,479 And in that callback, we're just going to assert, That 140 00:08:30,479 --> 00:08:35,392 the length of the found elements' array is greater than 0. 141 00:08:35,392 --> 00:08:41,520 That is, we're going to ensure that an invitedList element was found. 142 00:08:41,520 --> 00:08:43,962 Finally, we need to tell web diver to exit so 143 00:08:43,962 --> 00:08:47,280 it doesn't leave an open browser cluttering our desktop. 144 00:08:47,280 --> 00:08:52,070 So we'll take the promise that we get back from the previous function call. 145 00:08:53,810 --> 00:08:56,470 That one is not going to receive any parameters. 146 00:08:56,470 --> 00:08:59,520 And we'll say driver.quit. 147 00:09:01,340 --> 00:09:05,080 Let's save this, and go to our terminal and try running Mocha again. 148 00:09:06,400 --> 00:09:08,980 This time our test will actually connect to our site and 149 00:09:08,980 --> 00:09:12,380 confirm that the element we're looking for was found. 150 00:09:12,380 --> 00:09:16,680 Now, I don't know about you, but I find this promise syntax utterly confusing. 151 00:09:16,680 --> 00:09:20,450 If we miss any parenthesis or curly braces, it won't work. 152 00:09:20,450 --> 00:09:22,760 In the next video, I'll show you the async and 153 00:09:22,760 --> 00:09:25,850 await keywords, which will help simplify this code a lot.