1 00:00:00,000 --> 00:00:04,541 [MUSIC] 2 00:00:04,541 --> 00:00:09,415 This version of the RSVP app has been set up to load a list of people who've already 3 00:00:09,415 --> 00:00:11,890 been invited using an Ajax call. 4 00:00:11,890 --> 00:00:13,390 Each time I load the page, 5 00:00:13,390 --> 00:00:17,700 notice how the invitees take a second longer to load than the rest of the page. 6 00:00:17,700 --> 00:00:19,100 Actually, to tell the truth, 7 00:00:19,100 --> 00:00:22,200 I added an additional one second delay to the loading. 8 00:00:22,200 --> 00:00:25,130 But we get the same result if we were on a slow network 9 00:00:25,130 --> 00:00:28,290 if the server took a long time to send the Ajax response. 10 00:00:29,360 --> 00:00:33,200 This delay will be a problem if we want to write tests that ensure the invitees 11 00:00:33,200 --> 00:00:34,810 are being loaded properly. 12 00:00:34,810 --> 00:00:36,158 Let me show you what I mean. 13 00:00:36,158 --> 00:00:39,910 If we right-click on one of the invitee elements and choose Inspect, 14 00:00:39,910 --> 00:00:44,240 our browser development tools will load with the selected element highlighted. 15 00:00:44,240 --> 00:00:48,550 Notice that each invitee is being added as a list item element within this 16 00:00:48,550 --> 00:00:53,630 unordered list element, which has an ID of invited list. 17 00:00:53,630 --> 00:00:58,380 Let's say that our page object class had a locator for these list item elements. 18 00:00:58,380 --> 00:01:06,170 We'll give it a key of invitees and we'll us the By.CSS locator. 19 00:01:06,170 --> 00:01:10,580 We'll have it look for an element with an ID of invitedList. 20 00:01:13,290 --> 00:01:18,220 And then we're going to have it look for list item elements within that element. 21 00:01:18,220 --> 00:01:18,930 Let's save that. 22 00:01:20,060 --> 00:01:24,210 Now let's add a test to ensure that these invitee elements get loaded after the page 23 00:01:24,210 --> 00:01:24,720 loads. 24 00:01:25,870 --> 00:01:31,220 We'll add a test that says it, our RSVP page, loads existing 25 00:01:32,390 --> 00:01:37,760 invitations That will take an asynchronous function. 26 00:01:40,620 --> 00:01:42,270 We have no parameters. 27 00:01:44,130 --> 00:01:46,870 Now let's call our driver objects find elements method and 28 00:01:46,870 --> 00:01:48,560 assign the result to a variable. 29 00:01:48,560 --> 00:01:53,280 We'll say let invitees, this will return a promise, 30 00:01:53,280 --> 00:01:56,080 so we'll use await to wait for it. 31 00:01:56,080 --> 00:02:01,660 And we'll make a call to driver.findElements, 32 00:02:01,660 --> 00:02:04,570 and notice that's findElements plural, not singular. 33 00:02:04,570 --> 00:02:06,997 We expect to find multiple matching elements, so 34 00:02:06,997 --> 00:02:08,914 this will return an array of elements. 35 00:02:08,914 --> 00:02:16,119 We'll pass findElements the invitees locator from our page object. 36 00:02:16,119 --> 00:02:19,684 So page.locators.invitees. 37 00:02:22,637 --> 00:02:27,260 Now we need to test whether the invitees list loaded correctly. 38 00:02:27,260 --> 00:02:29,920 Each element contains the invitee's name, so 39 00:02:29,920 --> 00:02:32,130 I'm going to access the second invitee element. 40 00:02:33,665 --> 00:02:39,290 We're going to get the text from it, so we'll create a variable named text, 41 00:02:39,290 --> 00:02:42,680 the method we're going to use to get the element text returns a promise. 42 00:02:42,680 --> 00:02:46,520 So we'll type a wait here, and we'll make a call, 43 00:02:47,870 --> 00:02:54,280 we'll get the second element Invitees [1], and we'll get the text from it. 44 00:02:56,870 --> 00:02:58,280 And finally we need to test itself. 45 00:02:58,280 --> 00:03:04,090 I'm going to assert that the element text includes the string Craig Dennis. 46 00:03:15,980 --> 00:03:19,100 And that should match up with our second invitee here. 47 00:03:21,400 --> 00:03:27,410 Let's save this and go to our terminal and try running it with mocha. 48 00:03:30,690 --> 00:03:36,260 But it fails with the error, cannot read property 'getText' of undefined. 49 00:03:36,260 --> 00:03:40,810 We get this error because our attempt to find the invitee elements fails. 50 00:03:40,810 --> 00:03:44,650 Our call to find elements happens as soon as the page loads. 51 00:03:44,650 --> 00:03:48,510 WebDriver looks for LI elements within the invited list element. 52 00:03:48,510 --> 00:03:53,610 But at that moment, there are none, because the Ajax request hasn't completed. 53 00:03:53,610 --> 00:03:58,060 What we need is for WebDriver to wait a bit until the Ajax request completes, and 54 00:03:58,060 --> 00:03:59,160 the element has loaded. 55 00:04:00,380 --> 00:04:04,840 We can accomplish this by setting an implicit wait on our driver object. 56 00:04:04,840 --> 00:04:08,970 The wait is considered implicit because every time a function call is made that 57 00:04:08,970 --> 00:04:13,080 checks for an element, it's implied that the driver should wait a certain amount of 58 00:04:13,080 --> 00:04:15,430 time for the element to appear. 59 00:04:15,430 --> 00:04:18,570 So let's make the call that will set this implicit wait up. 60 00:04:18,570 --> 00:04:20,790 It returns a promise, like so many other methods. 61 00:04:20,790 --> 00:04:23,720 So we're gonna start with the await keyword. 62 00:04:23,720 --> 00:04:26,080 It's a method on our driver object. 63 00:04:26,080 --> 00:04:29,960 We manage the driver object by calling the manage method on it. 64 00:04:29,960 --> 00:04:33,050 And we're going to set the time outs that this driver uses. 65 00:04:33,050 --> 00:04:35,330 So we call the set time outs method. 66 00:04:36,500 --> 00:04:40,600 SetTimeouts takes an object with its attributes 67 00:04:40,600 --> 00:04:44,090 set to the various types of timeout that you want to set. 68 00:04:44,090 --> 00:04:49,260 We're going to set the implicit attribute, and this takes a value in milliseconds, 69 00:04:49,260 --> 00:04:54,000 that is thousandths of a second, that the driver is going to wait. 70 00:04:54,000 --> 00:04:59,430 So we're going to set an implicit timeout of 3,000 milliseconds, or 3 seconds. 71 00:05:00,570 --> 00:05:03,760 There are other options you can set using setTimeouts() as well. 72 00:05:03,760 --> 00:05:05,460 See the teacher's notes for more info. 73 00:05:06,640 --> 00:05:10,230 So with that implicit wait added, let's save our test, and 74 00:05:10,230 --> 00:05:12,320 go back to our terminal, and try re-running it. 75 00:05:14,300 --> 00:05:16,030 This time, the test is successful. 76 00:05:17,260 --> 00:05:21,040 When the call to driver.findElements is made, WebDriver will wait 77 00:05:21,040 --> 00:05:25,740 up to three seconds for matching elements to appear before continuing with the test. 78 00:05:25,740 --> 00:05:30,490 The test will only fail if the three seconds elapses without finding a match. 79 00:05:30,490 --> 00:05:32,680 There's a problem with this approach though, 80 00:05:32,680 --> 00:05:36,640 the implicit wait applies to all tests that use this driver object. 81 00:05:36,640 --> 00:05:40,130 This means that for each test, if the element you specified isn't 82 00:05:40,130 --> 00:05:44,980 present on the page, web driver will wait up to three seconds for it to appear. 83 00:05:44,980 --> 00:05:47,990 This is true even if you've made a mistake in your test or 84 00:05:47,990 --> 00:05:50,950 if the app has been changed so the test is failing. 85 00:05:50,950 --> 00:05:54,880 Implicit waits can make your failing test run much slower. 86 00:05:54,880 --> 00:05:55,770 In the next video, 87 00:05:55,770 --> 00:05:59,430 we'll look at explicit waits, which can help you avoid this problem.