Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / chrome / test / chromedriver / test / run_py_tests.py
1 #!/usr/bin/env python
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.
5
6 """End to end tests for ChromeDriver."""
7
8 import base64
9 import json
10 import math
11 import optparse
12 import os
13 import socket
14 import subprocess
15 import sys
16 import tempfile
17 import threading
18 import time
19 import unittest
20 import urllib2
21
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'))
26
27 import chrome_paths
28 import chromedriver
29 import unittest_util
30 import util
31 import server
32 from webelement import WebElement
33 import webserver
34
35 _TEST_DATA_DIR = os.path.join(chrome_paths.GetTestData(), 'chromedriver')
36
37 if util.IsLinux():
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
44
45
46 _NEGATIVE_FILTER = [
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',
52 ]
53
54 _VERSION_SPECIFIC_FILTER = {}
55 _VERSION_SPECIFIC_FILTER['HEAD'] = [
56     # https://code.google.com/p/chromedriver/issues/detail?id=815
57     'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
58 ]
59
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',
66 ]
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',
73 ]
74 _OS_SPECIFIC_FILTER['mac'] = [
75     # https://code.google.com/p/chromedriver/issues/detail?id=304
76     'ChromeDriverTest.testGoBackAndGoForward',
77 ]
78
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.*',
86 ]
87
88
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]
96   return filter
97
98 _ANDROID_NEGATIVE_FILTER = {}
99 _ANDROID_NEGATIVE_FILTER['chrome'] = (
100     _NEGATIVE_FILTER + [
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',
123     ]
124 )
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',
135     ]
136 )
137 _ANDROID_NEGATIVE_FILTER['chromedriver_webview_shell'] = (
138     _ANDROID_NEGATIVE_FILTER['chrome_shell'])
139
140
141 class ChromeDriverBaseTest(unittest.TestCase):
142   """Base class for testing chromedriver functionalities."""
143
144   def __init__(self, *args, **kwargs):
145     super(ChromeDriverBaseTest, self).__init__(*args, **kwargs)
146     self._drivers = []
147
148   def tearDown(self):
149     for driver in self._drivers:
150       try:
151         driver.Quit()
152       except:
153         pass
154
155   def CreateDriver(self, server_url=None, **kwargs):
156     if server_url is None:
157       server_url = _CHROMEDRIVER_SERVER_URL
158
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
167
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,
173                                        **kwargs)
174     self._drivers += [driver]
175     return driver
176
177
178 class ChromeDriverTest(ChromeDriverBaseTest):
179   """End to end tests for ChromeDriver."""
180
181   @staticmethod
182   def GlobalSetUp():
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)
194
195   @staticmethod
196   def GlobalTearDown():
197     if _ANDROID_PACKAGE_KEY:
198       forwarder.Forwarder.UnmapAllDevicePorts(ChromeDriverTest._device)
199     ChromeDriverTest._http_server.Shutdown()
200
201   @staticmethod
202   def GetHttpUrlForFile(file_path):
203     return ChromeDriverTest._http_server.GetUrl() + file_path
204
205   def setUp(self):
206     self._driver = self.CreateDriver()
207
208   def testStartStop(self):
209     pass
210
211   def testLoadUrl(self):
212     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
213
214   def testGetCurrentWindowHandle(self):
215     self._driver.GetCurrentWindowHandle()
216
217   def _WaitForNewWindow(self, old_handles):
218     """Wait for at least one new window to show up in 20 seconds.
219
220     Args:
221       old_handles: Handles to all old windows before the new window is added.
222
223     Returns:
224       Handle to a new window. None if timeout.
225     """
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)]
233       time.sleep(0.01)
234     return None
235
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()
256
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))
262
263   def testSwitchToWindow(self):
264     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
265     self.assertEquals(
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())
278
279   def testEvaluateScript(self):
280     self.assertEquals(1, self._driver.ExecuteScript('return 1'))
281     self.assertEquals(None, self._driver.ExecuteScript(''))
282
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'
288     self.assertEquals(
289         'bc', self._driver.ExecuteScript(script, stuff[0], stuff[1]))
290
291   def testEvaluateInvalidScript(self):
292     self.assertRaises(chromedriver.ChromeDriverException,
293                       self._driver.ExecuteScript, '{{{')
294
295   def testExecuteAsyncScript(self):
296     self._driver.SetTimeout('script', 3000)
297     self.assertRaises(
298         chromedriver.ScriptTimeout,
299         self._driver.ExecuteAsyncScript,
300         'var callback = arguments[0];'
301         'setTimeout(function(){callback(1);}, 10000);')
302     self.assertEquals(
303         2,
304         self._driver.ExecuteAsyncScript(
305             'var callback = arguments[0];'
306             'setTimeout(function(){callback(2);}, 300);'))
307
308   def testSwitchToFrame(self):
309     self._driver.ExecuteScript(
310         'var frame = document.createElement("iframe");'
311         'frame.id="id";'
312         'frame.name="name";'
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'))
329
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())
341
342   def testExecuteInRemovedFrame(self):
343     self._driver.ExecuteScript(
344         'var frame = document.createElement("iframe");'
345         'frame.id="id";'
346         'frame.name="name";'
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'))
355
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())
360
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())
364
365   def testFindElement(self):
366     self._driver.ExecuteScript(
367         'document.body.innerHTML = "<div>a</div><div>b</div>";')
368     self.assertTrue(
369         isinstance(self._driver.FindElement('tag name', 'div'), WebElement))
370
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))
377     for div in divs:
378       self.assertTrue(isinstance(div, WebElement))
379
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')
384     self.assertTrue(
385         isinstance(element.FindElement('tag name', 'br'), WebElement))
386
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))
394     for br in brs:
395       self.assertTrue(isinstance(br, WebElement))
396
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"));'
403         '});'
404         'return div;')
405     div.HoverOver()
406     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
407
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>";'
414         '});'
415         'return div;')
416     div.Click()
417     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
418
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>";'
425         '});'
426         'return div;')
427     div.SingleTap()
428     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
429
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>";'
436         '});'
437         'return div;')
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')))
442
443   def testTouchFlickElement(self):
444     dx = 3
445     dy = 4
446     speed = 5
447     flickTouchEventsPerSecond = 30
448     moveEvents = int(
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";'
455         '});'
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);'
460         '  }'
461         '});'
462         'div.addEventListener("touchend", function() {'
463         '  if (div.innerHTML == "preMove' + str(moveEvents) + '") {'
464         '    div.innerHTML = "new<br>";'
465         '  }'
466         '});'
467         'return div;')
468     self._driver.TouchFlick(div, dx, dy, speed)
469     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
470
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>";'
477         '});'
478         'return div;')
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')))
484
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()
491
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"));'
498         '});'
499         'return input;')
500     text.Clear()
501     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
502
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"));'
509         '});'
510         'return input;')
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)
515
516   def testGetCurrentUrl(self):
517     self.assertEquals('data:,', self._driver.GetCurrentUrl())
518
519   def testGoBackAndGoForward(self):
520     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
521     self._driver.GoBack()
522     self._driver.GoForward()
523
524   def testRefresh(self):
525     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
526     self._driver.Refresh()
527
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>";'
537         '});'
538         'return div;')
539     self._driver.MouseMoveTo(div, 10, 10)
540     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
541
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>";'
551         '});'
552         'return div;')
553     self._driver.MouseMoveTo(div)
554     self._driver.MouseClick()
555     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
556
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>";'
566         '});'
567         'div.addEventListener("mouseup", function() {'
568         '  var div = document.getElementsByTagName("div")[0];'
569         '  div.innerHTML="new2<a></a>";'
570         '});')
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')))
576
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>";'
586         '});'
587         'return div;')
588     self._driver.MouseMoveTo(div, 1, 1)
589     self._driver.MouseDoubleClick()
590     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
591
592   def testAlert(self):
593     self.assertFalse(self._driver.IsAlertOpen())
594     self._driver.ExecuteScript(
595         'window.setTimeout('
596         '    function() { window.confirmed = confirm(\'HI\'); },'
597         '    0);')
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'))
604
605   def testShouldHandleNewWindowLoadingProperly(self):
606     """Tests that ChromeDriver determines loading correctly for new windows."""
607     self._http_server.SetDataForPath(
608         '/newwindow',
609         """
610         <html>
611         <body>
612         <a href='%s' target='_blank'>new window/tab</a>
613         </body>
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)
620
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.
626
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)
633
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'))
640
641   def testWindowPosition(self):
642     position = self._driver.GetWindowPosition()
643     self._driver.SetWindowPosition(position[0], position[1])
644     self.assertEquals(position, self._driver.GetWindowPosition())
645
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)
649
650     self._driver.SetWindowPosition(100, 200)
651     self.assertEquals([100, 200], self._driver.GetWindowPosition())
652
653   def testWindowSize(self):
654     size = self._driver.GetWindowSize()
655     self._driver.SetWindowSize(size[0], size[1])
656     self.assertEquals(size, self._driver.GetWindowSize())
657
658     self._driver.SetWindowSize(600, 400)
659     self.assertEquals([600, 400], self._driver.GetWindowSize())
660
661   def testWindowMaximize(self):
662     self._driver.SetWindowPosition(100, 200)
663     self._driver.SetWindowSize(600, 400)
664     self._driver.MaximizeWindow()
665
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())
674
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')
681
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).*',
689                             self._driver.Load,
690                             url)
691
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'))
697
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()'))
702
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)
711
712   def testDoesntHangOnDebugger(self):
713     self._driver.ExecuteScript('debugger;')
714
715   def testMobileEmulationDisabledByDefault(self):
716     self.assertFalse(self._driver.capabilities['mobileEmulationEnabled'])
717
718
719 class ChromeDriverAndroidTest(ChromeDriverBaseTest):
720   """End to end tests for Android-specific tests."""
721
722   def testLatestAndroidAppInstalled(self):
723     if ('stable' not in _ANDROID_PACKAGE_KEY and
724         'beta' not in _ANDROID_PACKAGE_KEY):
725       return
726
727     self._driver = self.CreateDriver()
728
729     try:
730       omaha_list = json.loads(
731           urllib2.urlopen('http://omahaproxy.appspot.com/all.json').read())
732       for l in omaha_list:
733         if l['os'] != 'android':
734           continue
735         for v in l['versions']:
736           if (('stable' in v['channel'] and 'stable' in _ANDROID_PACKAGE_KEY) or
737               ('beta' in v['channel'] and 'beta' in _ANDROID_PACKAGE_KEY)):
738             self.assertEquals(v['version'],
739                               self._driver.capabilities['version'])
740             return
741       raise RuntimeError('Malformed omaha JSON')
742     except urllib2.URLError as e:
743       print 'Unable to fetch current version info from omahaproxy (%s)' % e
744
745   def testDeviceManagement(self):
746     self._drivers = [self.CreateDriver() for x in
747                      android_commands.GetAttachedDevices()]
748     self.assertRaises(chromedriver.UnknownError, self.CreateDriver)
749     self._drivers[0].Quit()
750     self._drivers[0] = self.CreateDriver()
751
752
753 class ChromeSwitchesCapabilityTest(ChromeDriverBaseTest):
754   """Tests that chromedriver properly processes chromeOptions.args capabilities.
755
756   Makes sure the switches are passed to Chrome.
757   """
758
759   def testSwitchWithoutArgument(self):
760     """Tests that switch --dom-automation can be passed to Chrome.
761
762     Unless --dom-automation is specified, window.domAutomationController
763     is undefined.
764     """
765     driver = self.CreateDriver(chrome_switches=['dom-automation'])
766     self.assertNotEqual(
767         None,
768         driver.ExecuteScript('return window.domAutomationController'))
769
770
771 class ChromeExtensionsCapabilityTest(ChromeDriverBaseTest):
772   """Tests that chromedriver properly processes chromeOptions.extensions."""
773
774   def _PackExtension(self, ext_path):
775     return base64.b64encode(open(ext_path, 'rb').read())
776
777   def testExtensionsInstall(self):
778     """Checks that chromedriver can take the extensions in crx format."""
779     crx_1 = os.path.join(_TEST_DATA_DIR, 'ext_test_1.crx')
780     crx_2 = os.path.join(_TEST_DATA_DIR, 'ext_test_2.crx')
781     self.CreateDriver(chrome_extensions=[self._PackExtension(crx_1),
782                                          self._PackExtension(crx_2)])
783
784   def testExtensionsInstallZip(self):
785     """Checks that chromedriver can take the extensions in zip format."""
786     zip_1 = os.path.join(_TEST_DATA_DIR, 'ext_test_1.zip')
787     self.CreateDriver(chrome_extensions=[self._PackExtension(zip_1)])
788
789   def testWaitsForExtensionToLoad(self):
790     did_load_event = threading.Event()
791     server = webserver.SyncWebServer()
792     def RunServer():
793       time.sleep(5)
794       server.RespondWithContent('<html>iframe</html>')
795       did_load_event.set()
796
797     thread = threading.Thread(target=RunServer)
798     thread.daemon = True
799     thread.start()
800     crx = os.path.join(_TEST_DATA_DIR, 'ext_slow_loader.crx')
801     driver = self.CreateDriver(
802         chrome_switches=['user-agent=' + server.GetUrl()],
803         chrome_extensions=[self._PackExtension(crx)])
804     self.assertTrue(did_load_event.is_set())
805
806
807 class ChromeLogPathCapabilityTest(ChromeDriverBaseTest):
808   """Tests that chromedriver properly processes chromeOptions.logPath."""
809
810   LOG_MESSAGE = 'Welcome to ChromeLogPathCapabilityTest!'
811
812   def testChromeLogPath(self):
813     """Checks that user can specify the path of the chrome log.
814
815     Verifies that a log message is written into the specified log file.
816     """
817     tmp_log_path = tempfile.NamedTemporaryFile()
818     driver = self.CreateDriver(chrome_log_path=tmp_log_path.name)
819     driver.ExecuteScript('console.info("%s")' % self.LOG_MESSAGE)
820     driver.Quit()
821     self.assertTrue(self.LOG_MESSAGE in open(tmp_log_path.name).read())
822
823
824 class MobileEmulationCapabilityTest(ChromeDriverBaseTest):
825   """Tests that ChromeDriver processes chromeOptions.mobileEmulation.
826
827   Makes sure the device metrics are overridden in DevTools and user agent is
828   overridden in Chrome.
829   """
830
831   @staticmethod
832   def GlobalSetUp():
833     def respondWithUserAgentString(request):
834       return request.GetHeader('User-Agent')
835
836     MobileEmulationCapabilityTest._http_server = webserver.WebServer(
837         chrome_paths.GetTestData())
838     MobileEmulationCapabilityTest._http_server.SetCallbackForPath(
839         '/userAgent', respondWithUserAgentString)
840
841   @staticmethod
842   def GlobalTearDown():
843     MobileEmulationCapabilityTest._http_server.Shutdown()
844
845   def testDeviceMetrics(self):
846     driver = self.CreateDriver(
847         mobile_emulation = {
848             'deviceMetrics': {'width': 360, 'height': 640, 'pixelRatio': 3}})
849     self.assertTrue(driver.capabilities['mobileEmulationEnabled'])
850     self.assertEqual(360, driver.ExecuteScript('return window.innerWidth'))
851     self.assertEqual(640, driver.ExecuteScript('return window.innerHeight'))
852
853   def testUserAgent(self):
854     driver = self.CreateDriver(
855         mobile_emulation = {'userAgent': 'Agent Smith'})
856     driver.Load(self._http_server.GetUrl() + '/userAgent')
857     body_tag = driver.FindElement('tag name', 'body')
858     self.assertEqual("Agent Smith", body_tag.GetText())
859
860   def testDeviceName(self):
861     driver = self.CreateDriver(
862         mobile_emulation = {'deviceName': 'Google Nexus 5'})
863     driver.Load(self._http_server.GetUrl() + '/userAgent')
864     self.assertEqual(360, driver.ExecuteScript('return window.innerWidth'))
865     self.assertEqual(640, driver.ExecuteScript('return window.innerHeight'))
866     body_tag = driver.FindElement('tag name', 'body')
867     self.assertEqual(
868         'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleW'
869         'ebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/53'
870         '5.19',
871         body_tag.GetText())
872
873
874 class ChromeDriverLogTest(unittest.TestCase):
875   """Tests that chromedriver produces the expected log file."""
876
877   UNEXPECTED_CHROMEOPTION_CAP = 'unexpected_chromeoption_capability'
878   LOG_MESSAGE = 'unrecognized chrome option: %s' % UNEXPECTED_CHROMEOPTION_CAP
879
880   def testChromeDriverLog(self):
881     _, tmp_log_path = tempfile.mkstemp(prefix='chromedriver_log_')
882     chromedriver_server = server.Server(
883         _CHROMEDRIVER_BINARY, log_path=tmp_log_path)
884     try:
885       driver = chromedriver.ChromeDriver(
886           chromedriver_server.GetUrl(), chrome_binary=_CHROME_BINARY,
887           experimental_options={ self.UNEXPECTED_CHROMEOPTION_CAP : 1 })
888       driver.Quit()
889     except chromedriver.ChromeDriverException, e:
890       self.assertTrue(self.LOG_MESSAGE in e.message)
891     finally:
892       chromedriver_server.Kill()
893     with open(tmp_log_path, 'r') as f:
894       self.assertTrue(self.LOG_MESSAGE in f.read())
895
896
897 class SessionHandlingTest(ChromeDriverBaseTest):
898   """Tests for session operations."""
899   def testQuitASessionMoreThanOnce(self):
900     driver = self.CreateDriver()
901     driver.Quit()
902     driver.Quit()
903
904
905 class RemoteBrowserTest(ChromeDriverBaseTest):
906   """Tests for ChromeDriver remote browser capability."""
907   def setUp(self):
908     self.assertTrue(_CHROME_BINARY is not None,
909                     'must supply a chrome binary arg')
910
911   def testConnectToRemoteBrowser(self):
912     port = self.FindFreePort()
913     temp_dir = util.MakeTempDir()
914     process = subprocess.Popen([_CHROME_BINARY,
915                                 '--remote-debugging-port=%d' % port,
916                                 '--user-data-dir=%s' % temp_dir])
917     if process is None:
918       raise RuntimeError('Chrome could not be started with debugging port')
919     try:
920       driver = self.CreateDriver(debugger_address='127.0.0.1:%d' % port)
921       driver.ExecuteScript('console.info("%s")' % 'connecting at %d!' % port)
922       driver.Quit()
923     finally:
924       process.terminate()
925
926   def FindFreePort(self):
927     for port in range(10000, 10100):
928       try:
929         socket.create_connection(('127.0.0.1', port), 0.2).close()
930       except socket.error:
931         return port
932     raise RuntimeError('Cannot find open port')
933
934 class PerfTest(ChromeDriverBaseTest):
935   """Tests for ChromeDriver perf."""
936   def setUp(self):
937     self.assertTrue(_REFERENCE_CHROMEDRIVER is not None,
938                     'must supply a reference-chromedriver arg')
939
940   def _RunDriverPerfTest(self, name, test_func):
941     """Runs a perf test comparing a reference and new ChromeDriver server.
942
943     Args:
944       name: The name of the perf test.
945       test_func: Called with the server url to perform the test action. Must
946                  return the time elapsed.
947     """
948     class Results(object):
949       ref = []
950       new = []
951
952     ref_server = server.Server(_REFERENCE_CHROMEDRIVER)
953     results = Results()
954     result_url_pairs = zip([results.new, results.ref],
955                            [_CHROMEDRIVER_SERVER_URL, ref_server.GetUrl()])
956     for iteration in range(30):
957       for result, url in result_url_pairs:
958         result += [test_func(url)]
959       # Reverse the order for the next run.
960       result_url_pairs = result_url_pairs[::-1]
961
962     def PrintResult(build, result):
963       mean = sum(result) / len(result)
964       avg_dev = sum([abs(sample - mean) for sample in result]) / len(result)
965       print 'perf result', build, name, mean, avg_dev, result
966       util.AddBuildStepText('%s %s: %.3f+-%.3f' % (
967           build, name, mean, avg_dev))
968
969     # Discard first result, which may be off due to cold start.
970     PrintResult('new', results.new[1:])
971     PrintResult('ref', results.ref[1:])
972
973   def testSessionStartTime(self):
974     def Run(url):
975       start = time.time()
976       driver = self.CreateDriver(url)
977       end = time.time()
978       driver.Quit()
979       return end - start
980     self._RunDriverPerfTest('session start', Run)
981
982   def testSessionStopTime(self):
983     def Run(url):
984       driver = self.CreateDriver(url)
985       start = time.time()
986       driver.Quit()
987       end = time.time()
988       return end - start
989     self._RunDriverPerfTest('session stop', Run)
990
991   def testColdExecuteScript(self):
992     def Run(url):
993       driver = self.CreateDriver(url)
994       start = time.time()
995       driver.ExecuteScript('return 1')
996       end = time.time()
997       driver.Quit()
998       return end - start
999     self._RunDriverPerfTest('cold exe js', Run)
1000
1001 if __name__ == '__main__':
1002   parser = optparse.OptionParser()
1003   parser.add_option(
1004       '', '--chromedriver',
1005       help='Path to chromedriver server (REQUIRED!)')
1006   parser.add_option(
1007       '', '--log-path',
1008       help='Output verbose server logs to this file')
1009   parser.add_option(
1010       '', '--reference-chromedriver',
1011       help='Path to the reference chromedriver server')
1012   parser.add_option(
1013       '', '--chrome', help='Path to a build of the chrome binary')
1014   parser.add_option(
1015       '', '--chrome-version', default='HEAD',
1016       help='Version of chrome. Default is \'HEAD\'.')
1017   parser.add_option(
1018       '', '--filter', type='string', default='*',
1019       help=('Filter for specifying what tests to run, "*" will run all. E.g., '
1020             '*testStartStop'))
1021   parser.add_option(
1022       '', '--android-package',
1023       help=('Android package key. Possible values: ' +
1024             str(_ANDROID_NEGATIVE_FILTER.keys())))
1025   options, args = parser.parse_args()
1026
1027   options.chromedriver = util.GetAbsolutePathOfUserPath(options.chromedriver)
1028   if not options.chromedriver or not os.path.exists(options.chromedriver):
1029     parser.error('chromedriver is required or the given path is invalid.' +
1030                  'Please run "%s --help" for help' % __file__)
1031
1032   global _CHROMEDRIVER_BINARY
1033   _CHROMEDRIVER_BINARY = options.chromedriver
1034
1035   if (options.android_package and
1036       options.android_package not in _ANDROID_NEGATIVE_FILTER):
1037     parser.error('Invalid --android-package')
1038
1039   chromedriver_server = server.Server(_CHROMEDRIVER_BINARY, options.log_path)
1040   global _CHROMEDRIVER_SERVER_URL
1041   _CHROMEDRIVER_SERVER_URL = chromedriver_server.GetUrl()
1042
1043   global _REFERENCE_CHROMEDRIVER
1044   _REFERENCE_CHROMEDRIVER = util.GetAbsolutePathOfUserPath(
1045       options.reference_chromedriver)
1046
1047   global _CHROME_BINARY
1048   if options.chrome:
1049     _CHROME_BINARY = util.GetAbsolutePathOfUserPath(options.chrome)
1050   else:
1051     _CHROME_BINARY = None
1052
1053   global _ANDROID_PACKAGE_KEY
1054   _ANDROID_PACKAGE_KEY = options.android_package
1055
1056   if options.filter == '*':
1057     if _ANDROID_PACKAGE_KEY:
1058       negative_filter = _ANDROID_NEGATIVE_FILTER[_ANDROID_PACKAGE_KEY]
1059     else:
1060       negative_filter = _GetDesktopNegativeFilter(options.chrome_version)
1061     options.filter = '*-' + ':__main__.'.join([''] + negative_filter)
1062
1063   all_tests_suite = unittest.defaultTestLoader.loadTestsFromModule(
1064       sys.modules[__name__])
1065   tests = unittest_util.FilterTestSuite(all_tests_suite, options.filter)
1066   ChromeDriverTest.GlobalSetUp()
1067   MobileEmulationCapabilityTest.GlobalSetUp()
1068   result = unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(tests)
1069   ChromeDriverTest.GlobalTearDown()
1070   MobileEmulationCapabilityTest.GlobalTearDown()
1071   sys.exit(len(result.failures) + len(result.errors))