2 # Copyright 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """End to end tests for ChromeDriver."""
22 _THIS_DIR = os.path.abspath(os.path.dirname(__file__))
23 sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir))
24 sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir, 'client'))
25 sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir, 'server'))
32 from webelement import WebElement
35 _TEST_DATA_DIR = os.path.join(chrome_paths.GetTestData(), 'chromedriver')
38 sys.path.insert(0, os.path.join(chrome_paths.GetSrc(), 'build', 'android'))
39 from pylib import android_commands
40 from pylib import constants
41 from pylib import forwarder
42 from pylib import valgrind_tools
43 from pylib.device import device_utils
47 # https://code.google.com/p/chromedriver/issues/detail?id=213
48 'ChromeDriverTest.testClickElementInSubFrame',
49 # This test is flaky since it uses setTimeout.
50 # Re-enable once crbug.com/177511 is fixed and we can remove setTimeout.
51 'ChromeDriverTest.testAlert',
54 _VERSION_SPECIFIC_FILTER = {}
55 _VERSION_SPECIFIC_FILTER['HEAD'] = [
56 # https://code.google.com/p/chromedriver/issues/detail?id=815
57 'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
60 _OS_SPECIFIC_FILTER = {}
61 _OS_SPECIFIC_FILTER['win'] = [
62 # https://code.google.com/p/chromedriver/issues/detail?id=214
63 'ChromeDriverTest.testCloseWindow',
64 # https://code.google.com/p/chromedriver/issues/detail?id=299
65 'ChromeLogPathCapabilityTest.testChromeLogPath',
67 _OS_SPECIFIC_FILTER['linux'] = [
68 # Xvfb doesn't support maximization.
69 'ChromeDriverTest.testWindowMaximize',
70 # https://code.google.com/p/chromedriver/issues/detail?id=302
71 'ChromeDriverTest.testWindowPosition',
72 'ChromeDriverTest.testWindowSize',
74 _OS_SPECIFIC_FILTER['mac'] = [
75 # https://code.google.com/p/chromedriver/issues/detail?id=304
76 'ChromeDriverTest.testGoBackAndGoForward',
79 _DESKTOP_NEGATIVE_FILTER = [
80 # Desktop doesn't support touch (without --touch-events).
81 'ChromeDriverTest.testSingleTapElement',
82 'ChromeDriverTest.testTouchDownUpElement',
83 'ChromeDriverTest.testTouchFlickElement',
84 'ChromeDriverTest.testTouchMovedElement',
85 'ChromeDriverAndroidTest.*',
89 def _GetDesktopNegativeFilter(version_name):
90 filter = _NEGATIVE_FILTER + _DESKTOP_NEGATIVE_FILTER
91 os = util.GetPlatformName()
92 if os in _OS_SPECIFIC_FILTER:
93 filter += _OS_SPECIFIC_FILTER[os]
94 if version_name in _VERSION_SPECIFIC_FILTER:
95 filter += _VERSION_SPECIFIC_FILTER[version_name]
98 _ANDROID_NEGATIVE_FILTER = {}
99 _ANDROID_NEGATIVE_FILTER['chrome'] = (
101 # TODO(chrisgao): fix hang of tab crash test on android.
102 'ChromeDriverTest.testTabCrash',
103 # Android doesn't support switches and extensions.
104 'ChromeSwitchesCapabilityTest.*',
105 'ChromeExtensionsCapabilityTest.*',
106 'MobileEmulationCapabilityTest.*',
107 # https://crbug.com/274650
108 'ChromeDriverTest.testCloseWindow',
109 # https://code.google.com/p/chromedriver/issues/detail?id=270
110 'ChromeDriverTest.testPopups',
111 # https://code.google.com/p/chromedriver/issues/detail?id=298
112 'ChromeDriverTest.testWindowPosition',
113 'ChromeDriverTest.testWindowSize',
114 'ChromeDriverTest.testWindowMaximize',
115 'ChromeLogPathCapabilityTest.testChromeLogPath',
116 'RemoteBrowserTest.*',
117 # Don't enable perf testing on Android yet.
118 'PerfTest.testSessionStartTime',
119 'PerfTest.testSessionStopTime',
120 'PerfTest.testColdExecuteScript',
121 # https://code.google.com/p/chromedriver/issues/detail?id=459
122 'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
125 _ANDROID_NEGATIVE_FILTER['chrome_stable'] = (
126 _ANDROID_NEGATIVE_FILTER['chrome'])
127 _ANDROID_NEGATIVE_FILTER['chrome_beta'] = (
128 _ANDROID_NEGATIVE_FILTER['chrome'])
129 _ANDROID_NEGATIVE_FILTER['chrome_shell'] = (
130 _ANDROID_NEGATIVE_FILTER['chrome'] + [
131 # ChromeShell doesn't support multiple tabs.
132 'ChromeDriverTest.testGetWindowHandles',
133 'ChromeDriverTest.testSwitchToWindow',
134 'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
137 _ANDROID_NEGATIVE_FILTER['chromedriver_webview_shell'] = (
138 _ANDROID_NEGATIVE_FILTER['chrome_shell'])
141 class ChromeDriverBaseTest(unittest.TestCase):
142 """Base class for testing chromedriver functionalities."""
144 def __init__(self, *args, **kwargs):
145 super(ChromeDriverBaseTest, self).__init__(*args, **kwargs)
149 for driver in self._drivers:
155 def CreateDriver(self, server_url=None, **kwargs):
156 if server_url is None:
157 server_url = _CHROMEDRIVER_SERVER_URL
159 android_package = None
160 android_activity = None
161 android_process = None
162 if _ANDROID_PACKAGE_KEY:
163 android_package = constants.PACKAGE_INFO[_ANDROID_PACKAGE_KEY].package
164 if _ANDROID_PACKAGE_KEY == 'chromedriver_webview_shell':
165 android_activity = constants.PACKAGE_INFO[_ANDROID_PACKAGE_KEY].activity
166 android_process = '%s:main' % android_package
168 driver = chromedriver.ChromeDriver(server_url,
169 chrome_binary=_CHROME_BINARY,
170 android_package=android_package,
171 android_activity=android_activity,
172 android_process=android_process,
174 self._drivers += [driver]
178 class ChromeDriverTest(ChromeDriverBaseTest):
179 """End to end tests for ChromeDriver."""
183 ChromeDriverTest._http_server = webserver.WebServer(
184 chrome_paths.GetTestData())
185 ChromeDriverTest._sync_server = webserver.SyncWebServer()
186 if _ANDROID_PACKAGE_KEY:
187 ChromeDriverTest._device = device_utils.DeviceUtils(
188 android_commands.GetAttachedDevices()[0])
189 http_host_port = ChromeDriverTest._http_server._server.server_port
190 sync_host_port = ChromeDriverTest._sync_server._server.server_port
191 forwarder.Forwarder.Map(
192 [(http_host_port, http_host_port), (sync_host_port, sync_host_port)],
193 ChromeDriverTest._device)
196 def GlobalTearDown():
197 if _ANDROID_PACKAGE_KEY:
198 forwarder.Forwarder.UnmapAllDevicePorts(ChromeDriverTest._device)
199 ChromeDriverTest._http_server.Shutdown()
202 def GetHttpUrlForFile(file_path):
203 return ChromeDriverTest._http_server.GetUrl() + file_path
206 self._driver = self.CreateDriver()
208 def testStartStop(self):
211 def testLoadUrl(self):
212 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
214 def testGetCurrentWindowHandle(self):
215 self._driver.GetCurrentWindowHandle()
217 def _WaitForNewWindow(self, old_handles):
218 """Wait for at least one new window to show up in 20 seconds.
221 old_handles: Handles to all old windows before the new window is added.
224 Handle to a new window. None if timeout.
226 timeout = time.time() + 20
227 while time.time() < timeout:
228 new_handles = self._driver.GetWindowHandles()
229 if len(new_handles) > len(old_handles):
230 for index, old_handle in enumerate(old_handles):
231 self.assertEquals(old_handle, new_handles[index])
232 return new_handles[len(old_handles)]
236 def testCloseWindow(self):
237 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
238 old_handles = self._driver.GetWindowHandles()
239 self._driver.FindElement('id', 'link').Click()
240 new_window_handle = self._WaitForNewWindow(old_handles)
241 self.assertNotEqual(None, new_window_handle)
242 self._driver.SwitchToWindow(new_window_handle)
243 self.assertEquals(new_window_handle, self._driver.GetCurrentWindowHandle())
244 self.assertRaises(chromedriver.NoSuchElement,
245 self._driver.FindElement, 'id', 'link')
246 self._driver.CloseWindow()
247 self.assertRaises(chromedriver.NoSuchWindow,
248 self._driver.GetCurrentWindowHandle)
249 new_handles = self._driver.GetWindowHandles()
250 for old_handle in old_handles:
251 self.assertTrue(old_handle in new_handles)
252 for handle in new_handles:
253 self._driver.SwitchToWindow(handle)
254 self.assertEquals(handle, self._driver.GetCurrentWindowHandle())
255 self._driver.CloseWindow()
257 def testGetWindowHandles(self):
258 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
259 old_handles = self._driver.GetWindowHandles()
260 self._driver.FindElement('id', 'link').Click()
261 self.assertNotEqual(None, self._WaitForNewWindow(old_handles))
263 def testSwitchToWindow(self):
264 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
266 1, self._driver.ExecuteScript('window.name = "oldWindow"; return 1;'))
267 window1_handle = self._driver.GetCurrentWindowHandle()
268 old_handles = self._driver.GetWindowHandles()
269 self._driver.FindElement('id', 'link').Click()
270 new_window_handle = self._WaitForNewWindow(old_handles)
271 self.assertNotEqual(None, new_window_handle)
272 self._driver.SwitchToWindow(new_window_handle)
273 self.assertEquals(new_window_handle, self._driver.GetCurrentWindowHandle())
274 self.assertRaises(chromedriver.NoSuchElement,
275 self._driver.FindElement, 'id', 'link')
276 self._driver.SwitchToWindow('oldWindow')
277 self.assertEquals(window1_handle, self._driver.GetCurrentWindowHandle())
279 def testEvaluateScript(self):
280 self.assertEquals(1, self._driver.ExecuteScript('return 1'))
281 self.assertEquals(None, self._driver.ExecuteScript(''))
283 def testEvaluateScriptWithArgs(self):
284 script = ('document.body.innerHTML = "<div>b</div><div>c</div>";'
285 'return {stuff: document.querySelectorAll("div")};')
286 stuff = self._driver.ExecuteScript(script)['stuff']
287 script = 'return arguments[0].innerHTML + arguments[1].innerHTML'
289 'bc', self._driver.ExecuteScript(script, stuff[0], stuff[1]))
291 def testEvaluateInvalidScript(self):
292 self.assertRaises(chromedriver.ChromeDriverException,
293 self._driver.ExecuteScript, '{{{')
295 def testExecuteAsyncScript(self):
296 self._driver.SetTimeout('script', 3000)
298 chromedriver.ScriptTimeout,
299 self._driver.ExecuteAsyncScript,
300 'var callback = arguments[0];'
301 'setTimeout(function(){callback(1);}, 10000);')
304 self._driver.ExecuteAsyncScript(
305 'var callback = arguments[0];'
306 'setTimeout(function(){callback(2);}, 300);'))
308 def testSwitchToFrame(self):
309 self._driver.ExecuteScript(
310 'var frame = document.createElement("iframe");'
313 'document.body.appendChild(frame);')
314 self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
315 self._driver.SwitchToFrame('id')
316 self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
317 self._driver.SwitchToMainFrame()
318 self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
319 self._driver.SwitchToFrame('name')
320 self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
321 self._driver.SwitchToMainFrame()
322 self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
323 self._driver.SwitchToFrameByIndex(0)
324 self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
325 self._driver.SwitchToMainFrame()
326 self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
327 self._driver.SwitchToFrame(self._driver.FindElement('tag name', 'iframe'))
328 self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
330 def testSwitchToParentFrame(self):
331 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/nested.html'))
332 self.assertTrue('One' in self._driver.GetPageSource())
333 self._driver.SwitchToFrameByIndex(0)
334 self.assertTrue('Two' in self._driver.GetPageSource())
335 self._driver.SwitchToFrameByIndex(0)
336 self.assertTrue('Three' in self._driver.GetPageSource())
337 self._driver.SwitchToParentFrame()
338 self.assertTrue('Two' in self._driver.GetPageSource())
339 self._driver.SwitchToParentFrame()
340 self.assertTrue('One' in self._driver.GetPageSource())
342 def testExecuteInRemovedFrame(self):
343 self._driver.ExecuteScript(
344 'var frame = document.createElement("iframe");'
347 'document.body.appendChild(frame);'
348 'window.addEventListener("message",'
349 ' function(event) { document.body.removeChild(frame); });')
350 self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
351 self._driver.SwitchToFrame('id')
352 self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
353 self._driver.ExecuteScript('parent.postMessage("remove", "*");')
354 self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
356 def testGetTitle(self):
357 script = 'document.title = "title"; return 1;'
358 self.assertEquals(1, self._driver.ExecuteScript(script))
359 self.assertEquals('title', self._driver.GetTitle())
361 def testGetPageSource(self):
362 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
363 self.assertTrue('Link to empty.html' in self._driver.GetPageSource())
365 def testFindElement(self):
366 self._driver.ExecuteScript(
367 'document.body.innerHTML = "<div>a</div><div>b</div>";')
369 isinstance(self._driver.FindElement('tag name', 'div'), WebElement))
371 def testFindElements(self):
372 self._driver.ExecuteScript(
373 'document.body.innerHTML = "<div>a</div><div>b</div>";')
374 divs = self._driver.FindElements('tag name', 'div')
375 self.assertTrue(isinstance(divs, list))
376 self.assertEquals(2, len(divs))
378 self.assertTrue(isinstance(div, WebElement))
380 def testFindChildElement(self):
381 self._driver.ExecuteScript(
382 'document.body.innerHTML = "<div><br><br></div><div><a></a></div>";')
383 element = self._driver.FindElement('tag name', 'div')
385 isinstance(element.FindElement('tag name', 'br'), WebElement))
387 def testFindChildElements(self):
388 self._driver.ExecuteScript(
389 'document.body.innerHTML = "<div><br><br></div><div><br></div>";')
390 element = self._driver.FindElement('tag name', 'div')
391 brs = element.FindElements('tag name', 'br')
392 self.assertTrue(isinstance(brs, list))
393 self.assertEquals(2, len(brs))
395 self.assertTrue(isinstance(br, WebElement))
397 def testHoverOverElement(self):
398 div = self._driver.ExecuteScript(
399 'document.body.innerHTML = "<div>old</div>";'
400 'var div = document.getElementsByTagName("div")[0];'
401 'div.addEventListener("mouseover", function() {'
402 ' document.body.appendChild(document.createElement("br"));'
406 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
408 def testClickElement(self):
409 div = self._driver.ExecuteScript(
410 'document.body.innerHTML = "<div>old</div>";'
411 'var div = document.getElementsByTagName("div")[0];'
412 'div.addEventListener("click", function() {'
413 ' div.innerHTML="new<br>";'
417 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
419 def testSingleTapElement(self):
420 div = self._driver.ExecuteScript(
421 'document.body.innerHTML = "<div>old</div>";'
422 'var div = document.getElementsByTagName("div")[0];'
423 'div.addEventListener("touchend", function() {'
424 ' div.innerHTML="new<br>";'
428 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
430 def testTouchDownUpElement(self):
431 div = self._driver.ExecuteScript(
432 'document.body.innerHTML = "<div>old</div>";'
433 'var div = document.getElementsByTagName("div")[0];'
434 'div.addEventListener("touchend", function() {'
435 ' div.innerHTML="new<br>";'
438 loc = div.GetLocation()
439 self._driver.TouchDown(loc['x'], loc['y'])
440 self._driver.TouchUp(loc['x'], loc['y'])
441 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
443 def testTouchFlickElement(self):
447 flickTouchEventsPerSecond = 30
449 math.sqrt(dx * dx + dy * dy) * flickTouchEventsPerSecond / speed)
450 div = self._driver.ExecuteScript(
451 'document.body.innerHTML = "<div>old</div>";'
452 'var div = document.getElementsByTagName("div")[0];'
453 'div.addEventListener("touchstart", function() {'
454 ' div.innerHTML = "preMove0";'
456 'div.addEventListener("touchmove", function() {'
457 ' res = div.innerHTML.match(/preMove(\d+)/);'
458 ' if (res != null) {'
459 ' div.innerHTML = "preMove" + (parseInt(res[1], 10) + 1);'
462 'div.addEventListener("touchend", function() {'
463 ' if (div.innerHTML == "preMove' + str(moveEvents) + '") {'
464 ' div.innerHTML = "new<br>";'
468 self._driver.TouchFlick(div, dx, dy, speed)
469 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
471 def testTouchMovedElement(self):
472 div = self._driver.ExecuteScript(
473 'document.body.innerHTML = "<div>old</div>";'
474 'var div = document.getElementsByTagName("div")[0];'
475 'div.addEventListener("touchmove", function() {'
476 ' div.innerHTML="new<br>";'
479 loc = div.GetLocation()
480 self._driver.TouchDown(loc['x'], loc['y'])
481 self._driver.TouchMove(loc['x'] + 1, loc['y'] + 1)
482 self._driver.TouchUp(loc['x'] + 1, loc['y'] + 1)
483 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
485 def testClickElementInSubFrame(self):
486 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/frame_test.html'))
487 frame = self._driver.FindElement('tag name', 'iframe')
488 self._driver.SwitchToFrame(frame)
489 # Test clicking element in the sub frame.
490 self.testClickElement()
492 def testClearElement(self):
493 text = self._driver.ExecuteScript(
494 'document.body.innerHTML = \'<input type="text" value="abc">\';'
495 'var input = document.getElementsByTagName("input")[0];'
496 'input.addEventListener("change", function() {'
497 ' document.body.appendChild(document.createElement("br"));'
501 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
503 def testSendKeysToElement(self):
504 text = self._driver.ExecuteScript(
505 'document.body.innerHTML = \'<input type="text">\';'
506 'var input = document.getElementsByTagName("input")[0];'
507 'input.addEventListener("change", function() {'
508 ' document.body.appendChild(document.createElement("br"));'
511 text.SendKeys('0123456789+-*/ Hi')
512 text.SendKeys(', there!')
513 value = self._driver.ExecuteScript('return arguments[0].value;', text)
514 self.assertEquals('0123456789+-*/ Hi, there!', value)
516 def testGetCurrentUrl(self):
517 self.assertEquals('data:,', self._driver.GetCurrentUrl())
519 def testGoBackAndGoForward(self):
520 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
521 self._driver.GoBack()
522 self._driver.GoForward()
524 def testRefresh(self):
525 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
526 self._driver.Refresh()
528 def testMouseMoveTo(self):
529 div = self._driver.ExecuteScript(
530 'document.body.innerHTML = "<div>old</div>";'
531 'var div = document.getElementsByTagName("div")[0];'
532 'div.style["width"] = "100px";'
533 'div.style["height"] = "100px";'
534 'div.addEventListener("mouseover", function() {'
535 ' var div = document.getElementsByTagName("div")[0];'
536 ' div.innerHTML="new<br>";'
539 self._driver.MouseMoveTo(div, 10, 10)
540 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
542 def testMouseClick(self):
543 div = self._driver.ExecuteScript(
544 'document.body.innerHTML = "<div>old</div>";'
545 'var div = document.getElementsByTagName("div")[0];'
546 'div.style["width"] = "100px";'
547 'div.style["height"] = "100px";'
548 'div.addEventListener("click", function() {'
549 ' var div = document.getElementsByTagName("div")[0];'
550 ' div.innerHTML="new<br>";'
553 self._driver.MouseMoveTo(div)
554 self._driver.MouseClick()
555 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
557 def testMouseButtonDownAndUp(self):
558 self._driver.ExecuteScript(
559 'document.body.innerHTML = "<div>old</div>";'
560 'var div = document.getElementsByTagName("div")[0];'
561 'div.style["width"] = "100px";'
562 'div.style["height"] = "100px";'
563 'div.addEventListener("mousedown", function() {'
564 ' var div = document.getElementsByTagName("div")[0];'
565 ' div.innerHTML="new1<br>";'
567 'div.addEventListener("mouseup", function() {'
568 ' var div = document.getElementsByTagName("div")[0];'
569 ' div.innerHTML="new2<a></a>";'
571 self._driver.MouseMoveTo(None, 50, 50)
572 self._driver.MouseButtonDown()
573 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
574 self._driver.MouseButtonUp()
575 self.assertEquals(1, len(self._driver.FindElements('tag name', 'a')))
577 def testMouseDoubleClick(self):
578 div = self._driver.ExecuteScript(
579 'document.body.innerHTML = "<div>old</div>";'
580 'var div = document.getElementsByTagName("div")[0];'
581 'div.style["width"] = "100px";'
582 'div.style["height"] = "100px";'
583 'div.addEventListener("dblclick", function() {'
584 ' var div = document.getElementsByTagName("div")[0];'
585 ' div.innerHTML="new<br>";'
588 self._driver.MouseMoveTo(div, 1, 1)
589 self._driver.MouseDoubleClick()
590 self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
593 self.assertFalse(self._driver.IsAlertOpen())
594 self._driver.ExecuteScript(
596 ' function() { window.confirmed = confirm(\'HI\'); },'
598 self.assertTrue(self._driver.IsAlertOpen())
599 self.assertEquals('HI', self._driver.GetAlertMessage())
600 self._driver.HandleAlert(False)
601 self.assertFalse(self._driver.IsAlertOpen())
602 self.assertEquals(False,
603 self._driver.ExecuteScript('return window.confirmed'))
605 def testShouldHandleNewWindowLoadingProperly(self):
606 """Tests that ChromeDriver determines loading correctly for new windows."""
607 self._http_server.SetDataForPath(
612 <a href='%s' target='_blank'>new window/tab</a>
614 </html>""" % self._sync_server.GetUrl())
615 self._driver.Load(self._http_server.GetUrl() + '/newwindow')
616 old_windows = self._driver.GetWindowHandles()
617 self._driver.FindElement('tagName', 'a').Click()
618 new_window = self._WaitForNewWindow(old_windows)
619 self.assertNotEqual(None, new_window)
621 self.assertFalse(self._driver.IsLoading())
622 self._driver.SwitchToWindow(new_window)
623 self.assertTrue(self._driver.IsLoading())
624 self._sync_server.RespondWithContent('<html>new window</html>')
625 self._driver.ExecuteScript('return 1') # Shouldn't hang.
627 def testPopups(self):
628 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
629 old_handles = self._driver.GetWindowHandles()
630 self._driver.ExecuteScript('window.open("about:blank")')
631 new_window_handle = self._WaitForNewWindow(old_handles)
632 self.assertNotEqual(None, new_window_handle)
634 def testNoSuchFrame(self):
635 self.assertRaises(chromedriver.NoSuchFrame,
636 self._driver.SwitchToFrame, 'nosuchframe')
637 self.assertRaises(chromedriver.NoSuchFrame,
638 self._driver.SwitchToFrame,
639 self._driver.FindElement('tagName', 'body'))
641 def testWindowPosition(self):
642 position = self._driver.GetWindowPosition()
643 self._driver.SetWindowPosition(position[0], position[1])
644 self.assertEquals(position, self._driver.GetWindowPosition())
646 # Resize so the window isn't moved offscreen.
647 # See https://code.google.com/p/chromedriver/issues/detail?id=297.
648 self._driver.SetWindowSize(300, 300)
650 self._driver.SetWindowPosition(100, 200)
651 self.assertEquals([100, 200], self._driver.GetWindowPosition())
653 def testWindowSize(self):
654 size = self._driver.GetWindowSize()
655 self._driver.SetWindowSize(size[0], size[1])
656 self.assertEquals(size, self._driver.GetWindowSize())
658 self._driver.SetWindowSize(600, 400)
659 self.assertEquals([600, 400], self._driver.GetWindowSize())
661 def testWindowMaximize(self):
662 self._driver.SetWindowPosition(100, 200)
663 self._driver.SetWindowSize(600, 400)
664 self._driver.MaximizeWindow()
666 self.assertNotEqual([100, 200], self._driver.GetWindowPosition())
667 self.assertNotEqual([600, 400], self._driver.GetWindowSize())
668 # Set size first so that the window isn't moved offscreen.
669 # See https://code.google.com/p/chromedriver/issues/detail?id=297.
670 self._driver.SetWindowSize(600, 400)
671 self._driver.SetWindowPosition(100, 200)
672 self.assertEquals([100, 200], self._driver.GetWindowPosition())
673 self.assertEquals([600, 400], self._driver.GetWindowSize())
675 def testConsoleLogSources(self):
676 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/console_log.html'))
677 logs = self._driver.GetLog('browser')
678 self.assertEquals(len(logs), 2)
679 self.assertEquals(logs[0]['source'], 'network')
680 self.assertEquals(logs[1]['source'], 'javascript')
682 def testAutoReporting(self):
683 self.assertFalse(self._driver.IsAutoReporting())
684 self._driver.SetAutoReporting(True)
685 self.assertTrue(self._driver.IsAutoReporting())
686 url = self.GetHttpUrlForFile('/chromedriver/console_log.html')
687 self.assertRaisesRegexp(chromedriver.UnknownError,
688 '.*(404|Failed to load resource).*',
692 def testContextMenuEventFired(self):
693 self._driver.Load(self.GetHttpUrlForFile('/chromedriver/context_menu.html'))
694 self._driver.MouseMoveTo(self._driver.FindElement('tagName', 'div'))
695 self._driver.MouseClick(2)
696 self.assertTrue(self._driver.ExecuteScript('return success'))
698 def testHasFocusOnStartup(self):
699 # Some pages (about:blank) cause Chrome to put the focus in URL bar.
700 # This breaks tests depending on focus.
701 self.assertTrue(self._driver.ExecuteScript('return document.hasFocus()'))
703 def testTabCrash(self):
704 # If a tab is crashed, the session will be deleted.
705 # When 31 is released, will reload the tab instead.
706 # https://code.google.com/p/chromedriver/issues/detail?id=547
707 self.assertRaises(chromedriver.UnknownError,
708 self._driver.Load, 'chrome://crash')
709 self.assertRaises(chromedriver.NoSuchSession,
710 self._driver.GetCurrentUrl)
712 def testDoesntHangOnDebugger(self):
713 self._driver.ExecuteScript('debugger;')
715 def testMobileEmulationDisabledByDefault(self):
716 self.assertFalse(self._driver.capabilities['mobileEmulationEnabled'])
718 def testChromeDriverSendLargeData(self):
719 script = 's = ""; for (i = 0; i < 10e6; i++) s += "0"; return s;'
720 lots_of_data = self._driver.ExecuteScript(script)
721 self.assertEquals('0'.zfill(int(10e6)), lots_of_data)
723 def testChromeDriverRecieveAndSendLargeData(self):
724 lots_of_data = '1'.zfill(int(10e6))
725 result = self._driver.ExecuteScript('return "%s"' % lots_of_data)
726 self.assertEquals(lots_of_data, result)
729 class ChromeDriverAndroidTest(ChromeDriverBaseTest):
730 """End to end tests for Android-specific tests."""
732 def testLatestAndroidAppInstalled(self):
733 if ('stable' not in _ANDROID_PACKAGE_KEY and
734 'beta' not in _ANDROID_PACKAGE_KEY):
737 self._driver = self.CreateDriver()
740 omaha_list = json.loads(
741 urllib2.urlopen('http://omahaproxy.appspot.com/all.json').read())
743 if l['os'] != 'android':
745 for v in l['versions']:
746 if (('stable' in v['channel'] and 'stable' in _ANDROID_PACKAGE_KEY) or
747 ('beta' in v['channel'] and 'beta' in _ANDROID_PACKAGE_KEY)):
748 omaha = map(int, v['version'].split('.'))
749 device = map(int, self._driver.capabilities['version'].split('.'))
750 self.assertTrue(omaha <= device)
752 raise RuntimeError('Malformed omaha JSON')
753 except urllib2.URLError as e:
754 print 'Unable to fetch current version info from omahaproxy (%s)' % e
756 def testDeviceManagement(self):
757 self._drivers = [self.CreateDriver() for x in
758 android_commands.GetAttachedDevices()]
759 self.assertRaises(chromedriver.UnknownError, self.CreateDriver)
760 self._drivers[0].Quit()
761 self._drivers[0] = self.CreateDriver()
764 class ChromeSwitchesCapabilityTest(ChromeDriverBaseTest):
765 """Tests that chromedriver properly processes chromeOptions.args capabilities.
767 Makes sure the switches are passed to Chrome.
770 def testSwitchWithoutArgument(self):
771 """Tests that switch --dom-automation can be passed to Chrome.
773 Unless --dom-automation is specified, window.domAutomationController
776 driver = self.CreateDriver(chrome_switches=['dom-automation'])
779 driver.ExecuteScript('return window.domAutomationController'))
782 class ChromeExtensionsCapabilityTest(ChromeDriverBaseTest):
783 """Tests that chromedriver properly processes chromeOptions.extensions."""
785 def _PackExtension(self, ext_path):
786 return base64.b64encode(open(ext_path, 'rb').read())
788 def testExtensionsInstall(self):
789 """Checks that chromedriver can take the extensions in crx format."""
790 crx_1 = os.path.join(_TEST_DATA_DIR, 'ext_test_1.crx')
791 crx_2 = os.path.join(_TEST_DATA_DIR, 'ext_test_2.crx')
792 self.CreateDriver(chrome_extensions=[self._PackExtension(crx_1),
793 self._PackExtension(crx_2)])
795 def testExtensionsInstallZip(self):
796 """Checks that chromedriver can take the extensions in zip format."""
797 zip_1 = os.path.join(_TEST_DATA_DIR, 'ext_test_1.zip')
798 self.CreateDriver(chrome_extensions=[self._PackExtension(zip_1)])
800 def testWaitsForExtensionToLoad(self):
801 did_load_event = threading.Event()
802 server = webserver.SyncWebServer()
805 server.RespondWithContent('<html>iframe</html>')
808 thread = threading.Thread(target=RunServer)
811 crx = os.path.join(_TEST_DATA_DIR, 'ext_slow_loader.crx')
812 driver = self.CreateDriver(
813 chrome_switches=['user-agent=' + server.GetUrl()],
814 chrome_extensions=[self._PackExtension(crx)])
815 self.assertTrue(did_load_event.is_set())
818 class ChromeLogPathCapabilityTest(ChromeDriverBaseTest):
819 """Tests that chromedriver properly processes chromeOptions.logPath."""
821 LOG_MESSAGE = 'Welcome to ChromeLogPathCapabilityTest!'
823 def testChromeLogPath(self):
824 """Checks that user can specify the path of the chrome log.
826 Verifies that a log message is written into the specified log file.
828 tmp_log_path = tempfile.NamedTemporaryFile()
829 driver = self.CreateDriver(chrome_log_path=tmp_log_path.name)
830 driver.ExecuteScript('console.info("%s")' % self.LOG_MESSAGE)
832 self.assertTrue(self.LOG_MESSAGE in open(tmp_log_path.name).read())
835 class MobileEmulationCapabilityTest(ChromeDriverBaseTest):
836 """Tests that ChromeDriver processes chromeOptions.mobileEmulation.
838 Makes sure the device metrics are overridden in DevTools and user agent is
839 overridden in Chrome.
844 def respondWithUserAgentString(request):
845 return request.GetHeader('User-Agent')
847 MobileEmulationCapabilityTest._http_server = webserver.WebServer(
848 chrome_paths.GetTestData())
849 MobileEmulationCapabilityTest._http_server.SetCallbackForPath(
850 '/userAgent', respondWithUserAgentString)
853 def GlobalTearDown():
854 MobileEmulationCapabilityTest._http_server.Shutdown()
856 def testDeviceMetrics(self):
857 driver = self.CreateDriver(
859 'deviceMetrics': {'width': 360, 'height': 640, 'pixelRatio': 3}})
860 self.assertTrue(driver.capabilities['mobileEmulationEnabled'])
861 self.assertEqual(360, driver.ExecuteScript('return window.innerWidth'))
862 self.assertEqual(640, driver.ExecuteScript('return window.innerHeight'))
864 def testUserAgent(self):
865 driver = self.CreateDriver(
866 mobile_emulation = {'userAgent': 'Agent Smith'})
867 driver.Load(self._http_server.GetUrl() + '/userAgent')
868 body_tag = driver.FindElement('tag name', 'body')
869 self.assertEqual("Agent Smith", body_tag.GetText())
871 def testDeviceName(self):
872 driver = self.CreateDriver(
873 mobile_emulation = {'deviceName': 'Google Nexus 5'})
874 driver.Load(self._http_server.GetUrl() + '/userAgent')
875 self.assertEqual(360, driver.ExecuteScript('return window.innerWidth'))
876 self.assertEqual(640, driver.ExecuteScript('return window.innerHeight'))
877 body_tag = driver.FindElement('tag name', 'body')
879 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleW'
880 'ebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/53'
884 def testSendKeysToElement(self):
885 driver = self.CreateDriver(
886 mobile_emulation = {'deviceName': 'Google Nexus 5'})
887 text = driver.ExecuteScript(
888 'document.body.innerHTML = \'<input type="text">\';'
889 'var input = document.getElementsByTagName("input")[0];'
890 'input.addEventListener("change", function() {'
891 ' document.body.appendChild(document.createElement("br"));'
894 text.SendKeys('0123456789+-*/ Hi')
895 text.SendKeys(', there!')
896 value = driver.ExecuteScript('return arguments[0].value;', text)
897 self.assertEquals('0123456789+-*/ Hi, there!', value)
899 def testHoverOverElement(self):
900 driver = self.CreateDriver(
901 mobile_emulation = {'deviceName': 'Google Nexus 5'})
902 div = driver.ExecuteScript(
903 'document.body.innerHTML = "<div>old</div>";'
904 'var div = document.getElementsByTagName("div")[0];'
905 'div.addEventListener("mouseover", function() {'
906 ' document.body.appendChild(document.createElement("br"));'
910 self.assertEquals(1, len(driver.FindElements('tag name', 'br')))
912 def testClickElement(self):
913 driver = self.CreateDriver(
914 mobile_emulation = {'deviceName': 'Google Nexus 5'})
915 div = driver.ExecuteScript(
916 'document.body.innerHTML = "<div>old</div>";'
917 'var div = document.getElementsByTagName("div")[0];'
918 'div.addEventListener("click", function() {'
919 ' div.innerHTML="new<br>";'
923 self.assertEquals(1, len(driver.FindElements('tag name', 'br')))
925 def testSingleTapElement(self):
926 driver = self.CreateDriver(
927 mobile_emulation = {'deviceName': 'Google Nexus 5'})
928 div = driver.ExecuteScript(
929 'document.body.innerHTML = "<div>old</div>";'
930 'var div = document.getElementsByTagName("div")[0];'
931 'div.addEventListener("touchend", function() {'
932 ' div.innerHTML="new<br>";'
936 self.assertEquals(1, len(driver.FindElements('tag name', 'br')))
938 def testTouchDownUpElement(self):
939 driver = self.CreateDriver(
940 mobile_emulation = {'deviceName': 'Google Nexus 5'})
941 div = driver.ExecuteScript(
942 'document.body.innerHTML = "<div>old</div>";'
943 'var div = document.getElementsByTagName("div")[0];'
944 'div.addEventListener("touchend", function() {'
945 ' div.innerHTML="new<br>";'
948 loc = div.GetLocation()
949 driver.TouchDown(loc['x'], loc['y'])
950 driver.TouchUp(loc['x'], loc['y'])
951 self.assertEquals(1, len(driver.FindElements('tag name', 'br')))
954 class ChromeDriverLogTest(unittest.TestCase):
955 """Tests that chromedriver produces the expected log file."""
957 UNEXPECTED_CHROMEOPTION_CAP = 'unexpected_chromeoption_capability'
958 LOG_MESSAGE = 'unrecognized chrome option: %s' % UNEXPECTED_CHROMEOPTION_CAP
960 def testChromeDriverLog(self):
961 _, tmp_log_path = tempfile.mkstemp(prefix='chromedriver_log_')
962 chromedriver_server = server.Server(
963 _CHROMEDRIVER_BINARY, log_path=tmp_log_path)
965 driver = chromedriver.ChromeDriver(
966 chromedriver_server.GetUrl(), chrome_binary=_CHROME_BINARY,
967 experimental_options={ self.UNEXPECTED_CHROMEOPTION_CAP : 1 })
969 except chromedriver.ChromeDriverException, e:
970 self.assertTrue(self.LOG_MESSAGE in e.message)
972 chromedriver_server.Kill()
973 with open(tmp_log_path, 'r') as f:
974 self.assertTrue(self.LOG_MESSAGE in f.read())
977 class PerformanceLoggerTest(ChromeDriverBaseTest):
978 """Tests chromedriver tracing support and Inspector event collection."""
980 def testPerformanceLogger(self):
981 driver = self.CreateDriver(
982 experimental_options={'perfLoggingPrefs': {
983 'enableTimeline': True,
984 'traceCategories': 'webkit.console,blink.console'
985 }}, performance_log_level='ALL')
987 ChromeDriverTest._http_server.GetUrl() + '/chromedriver/empty.html')
988 # Mark the timeline; later we will verify the marks appear in the trace.
989 driver.ExecuteScript('console.time("foobar")')
990 driver.ExecuteScript('console.timeEnd("foobar")')
991 logs = driver.GetLog('performance')
994 marked_timeline_events = []
995 seen_log_domains = {}
997 devtools_message = json.loads(entry['message'])['message']
998 method = devtools_message['method']
999 domain = method[:method.find('.')]
1000 seen_log_domains[domain] = True
1001 if method != 'Tracing.dataCollected':
1003 self.assertTrue('params' in devtools_message)
1004 self.assertTrue(isinstance(devtools_message['params'], dict))
1005 cat = devtools_message['params'].get('cat', '')
1006 # Depending on Chrome version, the events may occur for the webkit.console
1007 # or blink.console category. They will only occur for one of them.
1008 if (cat == 'blink.console' or cat == 'webkit.console'):
1009 self.assertTrue(devtools_message['params']['name'] == 'foobar')
1010 marked_timeline_events.append(devtools_message)
1011 self.assertEquals(2, len(marked_timeline_events))
1012 self.assertEquals({'Network', 'Page', 'Timeline', 'Tracing'},
1013 set(seen_log_domains.keys()))
1016 class SessionHandlingTest(ChromeDriverBaseTest):
1017 """Tests for session operations."""
1018 def testQuitASessionMoreThanOnce(self):
1019 driver = self.CreateDriver()
1024 class RemoteBrowserTest(ChromeDriverBaseTest):
1025 """Tests for ChromeDriver remote browser capability."""
1027 self.assertTrue(_CHROME_BINARY is not None,
1028 'must supply a chrome binary arg')
1030 def testConnectToRemoteBrowser(self):
1031 port = self.FindFreePort()
1032 temp_dir = util.MakeTempDir()
1033 process = subprocess.Popen([_CHROME_BINARY,
1034 '--remote-debugging-port=%d' % port,
1035 '--user-data-dir=%s' % temp_dir])
1037 raise RuntimeError('Chrome could not be started with debugging port')
1039 driver = self.CreateDriver(debugger_address='127.0.0.1:%d' % port)
1040 driver.ExecuteScript('console.info("%s")' % 'connecting at %d!' % port)
1045 def FindFreePort(self):
1046 for port in range(10000, 10100):
1048 socket.create_connection(('127.0.0.1', port), 0.2).close()
1049 except socket.error:
1051 raise RuntimeError('Cannot find open port')
1053 class PerfTest(ChromeDriverBaseTest):
1054 """Tests for ChromeDriver perf."""
1056 self.assertTrue(_REFERENCE_CHROMEDRIVER is not None,
1057 'must supply a reference-chromedriver arg')
1059 def _RunDriverPerfTest(self, name, test_func):
1060 """Runs a perf test comparing a reference and new ChromeDriver server.
1063 name: The name of the perf test.
1064 test_func: Called with the server url to perform the test action. Must
1065 return the time elapsed.
1067 class Results(object):
1071 ref_server = server.Server(_REFERENCE_CHROMEDRIVER)
1073 result_url_pairs = zip([results.new, results.ref],
1074 [_CHROMEDRIVER_SERVER_URL, ref_server.GetUrl()])
1075 for iteration in range(30):
1076 for result, url in result_url_pairs:
1077 result += [test_func(url)]
1078 # Reverse the order for the next run.
1079 result_url_pairs = result_url_pairs[::-1]
1081 def PrintResult(build, result):
1082 mean = sum(result) / len(result)
1083 avg_dev = sum([abs(sample - mean) for sample in result]) / len(result)
1084 print 'perf result', build, name, mean, avg_dev, result
1085 util.AddBuildStepText('%s %s: %.3f+-%.3f' % (
1086 build, name, mean, avg_dev))
1088 # Discard first result, which may be off due to cold start.
1089 PrintResult('new', results.new[1:])
1090 PrintResult('ref', results.ref[1:])
1092 def testSessionStartTime(self):
1095 driver = self.CreateDriver(url)
1099 self._RunDriverPerfTest('session start', Run)
1101 def testSessionStopTime(self):
1103 driver = self.CreateDriver(url)
1108 self._RunDriverPerfTest('session stop', Run)
1110 def testColdExecuteScript(self):
1112 driver = self.CreateDriver(url)
1114 driver.ExecuteScript('return 1')
1118 self._RunDriverPerfTest('cold exe js', Run)
1120 if __name__ == '__main__':
1121 parser = optparse.OptionParser()
1123 '', '--chromedriver',
1124 help='Path to chromedriver server (REQUIRED!)')
1127 help='Output verbose server logs to this file')
1129 '', '--reference-chromedriver',
1130 help='Path to the reference chromedriver server')
1132 '', '--chrome', help='Path to a build of the chrome binary')
1134 '', '--chrome-version', default='HEAD',
1135 help='Version of chrome. Default is \'HEAD\'.')
1137 '', '--filter', type='string', default='*',
1138 help=('Filter for specifying what tests to run, "*" will run all. E.g., '
1141 '', '--android-package',
1142 help=('Android package key. Possible values: ' +
1143 str(_ANDROID_NEGATIVE_FILTER.keys())))
1144 options, args = parser.parse_args()
1146 options.chromedriver = util.GetAbsolutePathOfUserPath(options.chromedriver)
1147 if not options.chromedriver or not os.path.exists(options.chromedriver):
1148 parser.error('chromedriver is required or the given path is invalid.' +
1149 'Please run "%s --help" for help' % __file__)
1151 global _CHROMEDRIVER_BINARY
1152 _CHROMEDRIVER_BINARY = options.chromedriver
1154 if (options.android_package and
1155 options.android_package not in _ANDROID_NEGATIVE_FILTER):
1156 parser.error('Invalid --android-package')
1158 chromedriver_server = server.Server(_CHROMEDRIVER_BINARY, options.log_path)
1159 global _CHROMEDRIVER_SERVER_URL
1160 _CHROMEDRIVER_SERVER_URL = chromedriver_server.GetUrl()
1162 global _REFERENCE_CHROMEDRIVER
1163 _REFERENCE_CHROMEDRIVER = util.GetAbsolutePathOfUserPath(
1164 options.reference_chromedriver)
1166 global _CHROME_BINARY
1168 _CHROME_BINARY = util.GetAbsolutePathOfUserPath(options.chrome)
1170 _CHROME_BINARY = None
1172 global _ANDROID_PACKAGE_KEY
1173 _ANDROID_PACKAGE_KEY = options.android_package
1175 if options.filter == '*':
1176 if _ANDROID_PACKAGE_KEY:
1177 negative_filter = _ANDROID_NEGATIVE_FILTER[_ANDROID_PACKAGE_KEY]
1179 negative_filter = _GetDesktopNegativeFilter(options.chrome_version)
1180 options.filter = '*-' + ':__main__.'.join([''] + negative_filter)
1182 all_tests_suite = unittest.defaultTestLoader.loadTestsFromModule(
1183 sys.modules[__name__])
1184 tests = unittest_util.FilterTestSuite(all_tests_suite, options.filter)
1185 ChromeDriverTest.GlobalSetUp()
1186 MobileEmulationCapabilityTest.GlobalSetUp()
1187 result = unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(tests)
1188 ChromeDriverTest.GlobalTearDown()
1189 MobileEmulationCapabilityTest.GlobalTearDown()
1190 sys.exit(len(result.failures) + len(result.errors))