Upstream version 5.34.104.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
44
45 _NEGATIVE_FILTER = [
46     # https://code.google.com/p/chromedriver/issues/detail?id=213
47     'ChromeDriverTest.testClickElementInSubFrame',
48     # This test is flaky since it uses setTimeout.
49     # Re-enable once crbug.com/177511 is fixed and we can remove setTimeout.
50     'ChromeDriverTest.testAlert',
51 ]
52
53 _VERSION_SPECIFIC_FILTER = {}
54 _VERSION_SPECIFIC_FILTER['HEAD'] = []
55
56 _OS_SPECIFIC_FILTER = {}
57 _OS_SPECIFIC_FILTER['win'] = [
58     # https://code.google.com/p/chromedriver/issues/detail?id=214
59     'ChromeDriverTest.testCloseWindow',
60     # https://code.google.com/p/chromedriver/issues/detail?id=299
61     'ChromeLogPathCapabilityTest.testChromeLogPath',
62 ]
63 _OS_SPECIFIC_FILTER['linux'] = [
64     # Xvfb doesn't support maximization.
65     'ChromeDriverTest.testWindowMaximize',
66     # https://code.google.com/p/chromedriver/issues/detail?id=302
67     'ChromeDriverTest.testWindowPosition',
68     'ChromeDriverTest.testWindowSize',
69 ]
70 _OS_SPECIFIC_FILTER['mac'] = [
71     # https://code.google.com/p/chromedriver/issues/detail?id=304
72     'ChromeDriverTest.testGoBackAndGoForward',
73 ]
74
75 _DESKTOP_NEGATIVE_FILTER = [
76     # Desktop doesn't support touch (without --touch-events).
77     'ChromeDriverTest.testSingleTapElement',
78     'ChromeDriverTest.testTouchDownUpElement',
79     'ChromeDriverTest.testTouchFlickElement',
80     'ChromeDriverTest.testTouchMovedElement',
81     'ChromeDriverAndroidTest.*',
82 ]
83
84
85 def _GetDesktopNegativeFilter(version_name):
86   filter = _NEGATIVE_FILTER + _DESKTOP_NEGATIVE_FILTER
87   os = util.GetPlatformName()
88   if os in _OS_SPECIFIC_FILTER:
89     filter += _OS_SPECIFIC_FILTER[os]
90   if version_name in _VERSION_SPECIFIC_FILTER:
91     filter += _VERSION_SPECIFIC_FILTER[version_name]
92   return filter
93
94 _ANDROID_NEGATIVE_FILTER = {}
95 _ANDROID_NEGATIVE_FILTER['chrome'] = (
96     _NEGATIVE_FILTER + [
97         # TODO(chrisgao): fix hang of tab crash test on android.
98         'ChromeDriverTest.testTabCrash',
99         # Android doesn't support switches and extensions.
100         'ChromeSwitchesCapabilityTest.*',
101         'ChromeExtensionsCapabilityTest.*',
102         # https://crbug.com/274650
103         'ChromeDriverTest.testCloseWindow',
104         # https://code.google.com/p/chromedriver/issues/detail?id=270
105         'ChromeDriverTest.testPopups',
106         # https://code.google.com/p/chromedriver/issues/detail?id=298
107         'ChromeDriverTest.testWindowPosition',
108         'ChromeDriverTest.testWindowSize',
109         'ChromeDriverTest.testWindowMaximize',
110         'ChromeLogPathCapabilityTest.testChromeLogPath',
111         'ExistingBrowserTest.*',
112         # Don't enable perf testing on Android yet.
113         'PerfTest.testSessionStartTime',
114         'PerfTest.testSessionStopTime',
115         'PerfTest.testColdExecuteScript',
116         # https://code.google.com/p/chromedriver/issues/detail?id=459
117         'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
118     ]
119 )
120 _ANDROID_NEGATIVE_FILTER['chrome_stable'] = (
121     _ANDROID_NEGATIVE_FILTER['chrome'])
122 _ANDROID_NEGATIVE_FILTER['chrome_beta'] = (
123     _ANDROID_NEGATIVE_FILTER['chrome'])
124 _ANDROID_NEGATIVE_FILTER['chromium_test_shell'] = (
125     _ANDROID_NEGATIVE_FILTER['chrome'] + [
126         # ChromiumTestShell doesn't support multiple tabs.
127         'ChromeDriverTest.testGetWindowHandles',
128         'ChromeDriverTest.testSwitchToWindow',
129         'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
130     ]
131 )
132 _ANDROID_NEGATIVE_FILTER['chromedriver_webview_shell'] = (
133     _ANDROID_NEGATIVE_FILTER['chromium_test_shell'])
134
135
136 class ChromeDriverBaseTest(unittest.TestCase):
137   """Base class for testing chromedriver functionalities."""
138
139   def __init__(self, *args, **kwargs):
140     super(ChromeDriverBaseTest, self).__init__(*args, **kwargs)
141     self._drivers = []
142
143   def tearDown(self):
144     for driver in self._drivers:
145       try:
146         driver.Quit()
147       except:
148         pass
149
150   def CreateDriver(self, server_url=None, **kwargs):
151     if server_url is None:
152       server_url = _CHROMEDRIVER_SERVER_URL
153
154     android_package = None
155     android_activity = None
156     android_process = None
157     if _ANDROID_PACKAGE_KEY:
158       android_package = constants.PACKAGE_INFO[_ANDROID_PACKAGE_KEY].package
159       if _ANDROID_PACKAGE_KEY == 'chromedriver_webview_shell':
160         android_activity = constants.PACKAGE_INFO[_ANDROID_PACKAGE_KEY].activity
161         android_process = '%s:main' % android_package
162
163     driver = chromedriver.ChromeDriver(server_url,
164                                        chrome_binary=_CHROME_BINARY,
165                                        android_package=android_package,
166                                        android_activity=android_activity,
167                                        android_process=android_process,
168                                        **kwargs)
169     self._drivers += [driver]
170     return driver
171
172
173 class ChromeDriverTest(ChromeDriverBaseTest):
174   """End to end tests for ChromeDriver."""
175
176   @staticmethod
177   def GlobalSetUp():
178     ChromeDriverTest._http_server = webserver.WebServer(
179         chrome_paths.GetTestData())
180     ChromeDriverTest._sync_server = webserver.SyncWebServer()
181     if _ANDROID_PACKAGE_KEY:
182       ChromeDriverTest._adb = android_commands.AndroidCommands(
183           android_commands.GetAttachedDevices()[0])
184       http_host_port = ChromeDriverTest._http_server._server.server_port
185       sync_host_port = ChromeDriverTest._sync_server._server.server_port
186       forwarder.Forwarder.Map(
187           [(http_host_port, http_host_port), (sync_host_port, sync_host_port)],
188           ChromeDriverTest._adb)
189
190   @staticmethod
191   def GlobalTearDown():
192     if _ANDROID_PACKAGE_KEY:
193       forwarder.Forwarder.UnmapAllDevicePorts(ChromeDriverTest._adb)
194     ChromeDriverTest._http_server.Shutdown()
195
196   @staticmethod
197   def GetHttpUrlForFile(file_path):
198     return ChromeDriverTest._http_server.GetUrl() + file_path
199
200   def setUp(self):
201     self._driver = self.CreateDriver()
202
203   def testStartStop(self):
204     pass
205
206   def testLoadUrl(self):
207     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
208
209   def testGetCurrentWindowHandle(self):
210     self._driver.GetCurrentWindowHandle()
211
212   def _WaitForNewWindow(self, old_handles):
213     """Wait for at least one new window to show up in 20 seconds.
214
215     Args:
216       old_handles: Handles to all old windows before the new window is added.
217
218     Returns:
219       Handle to a new window. None if timeout.
220     """
221     timeout = time.time() + 20
222     while time.time() < timeout:
223       new_handles = self._driver.GetWindowHandles()
224       if len(new_handles) > len(old_handles):
225         for index, old_handle in enumerate(old_handles):
226           self.assertEquals(old_handle, new_handles[index])
227         return new_handles[len(old_handles)]
228       time.sleep(0.01)
229     return None
230
231   def testCloseWindow(self):
232     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
233     old_handles = self._driver.GetWindowHandles()
234     self._driver.FindElement('id', 'link').Click()
235     new_window_handle = self._WaitForNewWindow(old_handles)
236     self.assertNotEqual(None, new_window_handle)
237     self._driver.SwitchToWindow(new_window_handle)
238     self.assertEquals(new_window_handle, self._driver.GetCurrentWindowHandle())
239     self.assertRaises(chromedriver.NoSuchElement,
240                       self._driver.FindElement, 'id', 'link')
241     self._driver.CloseWindow()
242     self.assertRaises(chromedriver.NoSuchWindow,
243                       self._driver.GetCurrentWindowHandle)
244     new_handles = self._driver.GetWindowHandles()
245     for old_handle in old_handles:
246       self.assertTrue(old_handle in new_handles)
247     for handle in new_handles:
248       self._driver.SwitchToWindow(handle)
249       self.assertEquals(handle, self._driver.GetCurrentWindowHandle())
250       self._driver.CloseWindow()
251
252   def testGetWindowHandles(self):
253     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
254     old_handles = self._driver.GetWindowHandles()
255     self._driver.FindElement('id', 'link').Click()
256     self.assertNotEqual(None, self._WaitForNewWindow(old_handles))
257
258   def testSwitchToWindow(self):
259     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
260     self.assertEquals(
261         1, self._driver.ExecuteScript('window.name = "oldWindow"; return 1;'))
262     window1_handle = self._driver.GetCurrentWindowHandle()
263     old_handles = self._driver.GetWindowHandles()
264     self._driver.FindElement('id', 'link').Click()
265     new_window_handle = self._WaitForNewWindow(old_handles)
266     self.assertNotEqual(None, new_window_handle)
267     self._driver.SwitchToWindow(new_window_handle)
268     self.assertEquals(new_window_handle, self._driver.GetCurrentWindowHandle())
269     self.assertRaises(chromedriver.NoSuchElement,
270                       self._driver.FindElement, 'id', 'link')
271     self._driver.SwitchToWindow('oldWindow')
272     self.assertEquals(window1_handle, self._driver.GetCurrentWindowHandle())
273
274   def testEvaluateScript(self):
275     self.assertEquals(1, self._driver.ExecuteScript('return 1'))
276     self.assertEquals(None, self._driver.ExecuteScript(''))
277
278   def testEvaluateScriptWithArgs(self):
279     script = ('document.body.innerHTML = "<div>b</div><div>c</div>";'
280               'return {stuff: document.querySelectorAll("div")};')
281     stuff = self._driver.ExecuteScript(script)['stuff']
282     script = 'return arguments[0].innerHTML + arguments[1].innerHTML'
283     self.assertEquals(
284         'bc', self._driver.ExecuteScript(script, stuff[0], stuff[1]))
285
286   def testEvaluateInvalidScript(self):
287     self.assertRaises(chromedriver.ChromeDriverException,
288                       self._driver.ExecuteScript, '{{{')
289
290   def testExecuteAsyncScript(self):
291     self._driver.SetTimeout('script', 3000)
292     self.assertRaises(
293         chromedriver.ScriptTimeout,
294         self._driver.ExecuteAsyncScript,
295         'var callback = arguments[0];'
296         'setTimeout(function(){callback(1);}, 10000);')
297     self.assertEquals(
298         2,
299         self._driver.ExecuteAsyncScript(
300             'var callback = arguments[0];'
301             'setTimeout(function(){callback(2);}, 300);'))
302
303   def testSwitchToFrame(self):
304     self._driver.ExecuteScript(
305         'var frame = document.createElement("iframe");'
306         'frame.id="id";'
307         'frame.name="name";'
308         'document.body.appendChild(frame);')
309     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
310     self._driver.SwitchToFrame('id')
311     self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
312     self._driver.SwitchToMainFrame()
313     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
314     self._driver.SwitchToFrame('name')
315     self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
316     self._driver.SwitchToMainFrame()
317     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
318     self._driver.SwitchToFrameByIndex(0)
319     self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
320     self._driver.SwitchToMainFrame()
321     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
322     self._driver.SwitchToFrame(self._driver.FindElement('tag name', 'iframe'))
323     self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
324
325   def testExecuteInRemovedFrame(self):
326     self._driver.ExecuteScript(
327         'var frame = document.createElement("iframe");'
328         'frame.id="id";'
329         'frame.name="name";'
330         'document.body.appendChild(frame);'
331         'window.addEventListener("message",'
332         '    function(event) { document.body.removeChild(frame); });')
333     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
334     self._driver.SwitchToFrame('id')
335     self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
336     self._driver.ExecuteScript('parent.postMessage("remove", "*");')
337     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
338
339   def testGetTitle(self):
340     script = 'document.title = "title"; return 1;'
341     self.assertEquals(1, self._driver.ExecuteScript(script))
342     self.assertEquals('title', self._driver.GetTitle())
343
344   def testGetPageSource(self):
345     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
346     self.assertTrue('Link to empty.html' in self._driver.GetPageSource())
347
348   def testFindElement(self):
349     self._driver.ExecuteScript(
350         'document.body.innerHTML = "<div>a</div><div>b</div>";')
351     self.assertTrue(
352         isinstance(self._driver.FindElement('tag name', 'div'), WebElement))
353
354   def testFindElements(self):
355     self._driver.ExecuteScript(
356         'document.body.innerHTML = "<div>a</div><div>b</div>";')
357     divs = self._driver.FindElements('tag name', 'div')
358     self.assertTrue(isinstance(divs, list))
359     self.assertEquals(2, len(divs))
360     for div in divs:
361       self.assertTrue(isinstance(div, WebElement))
362
363   def testFindChildElement(self):
364     self._driver.ExecuteScript(
365         'document.body.innerHTML = "<div><br><br></div><div><a></a></div>";')
366     element = self._driver.FindElement('tag name', 'div')
367     self.assertTrue(
368         isinstance(element.FindElement('tag name', 'br'), WebElement))
369
370   def testFindChildElements(self):
371     self._driver.ExecuteScript(
372         'document.body.innerHTML = "<div><br><br></div><div><br></div>";')
373     element = self._driver.FindElement('tag name', 'div')
374     brs = element.FindElements('tag name', 'br')
375     self.assertTrue(isinstance(brs, list))
376     self.assertEquals(2, len(brs))
377     for br in brs:
378       self.assertTrue(isinstance(br, WebElement))
379
380   def testHoverOverElement(self):
381     div = self._driver.ExecuteScript(
382         'document.body.innerHTML = "<div>old</div>";'
383         'var div = document.getElementsByTagName("div")[0];'
384         'div.addEventListener("mouseover", function() {'
385         '  document.body.appendChild(document.createElement("br"));'
386         '});'
387         'return div;')
388     div.HoverOver()
389     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
390
391   def testClickElement(self):
392     div = self._driver.ExecuteScript(
393         'document.body.innerHTML = "<div>old</div>";'
394         'var div = document.getElementsByTagName("div")[0];'
395         'div.addEventListener("click", function() {'
396         '  div.innerHTML="new<br>";'
397         '});'
398         'return div;')
399     div.Click()
400     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
401
402   def testSingleTapElement(self):
403     div = self._driver.ExecuteScript(
404         'document.body.innerHTML = "<div>old</div>";'
405         'var div = document.getElementsByTagName("div")[0];'
406         'div.addEventListener("touchend", function() {'
407         '  div.innerHTML="new<br>";'
408         '});'
409         'return div;')
410     div.SingleTap()
411     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
412
413   def testTouchDownUpElement(self):
414     div = self._driver.ExecuteScript(
415         'document.body.innerHTML = "<div>old</div>";'
416         'var div = document.getElementsByTagName("div")[0];'
417         'div.addEventListener("touchend", function() {'
418         '  div.innerHTML="new<br>";'
419         '});'
420         'return div;')
421     loc = div.GetLocation()
422     self._driver.TouchDown(loc['x'], loc['y'])
423     self._driver.TouchUp(loc['x'], loc['y'])
424     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
425
426   def testTouchFlickElement(self):
427     dx = 3
428     dy = 4
429     speed = 5
430     flickTouchEventsPerSecond = 30
431     moveEvents = int(
432         math.sqrt(dx * dx + dy * dy) * flickTouchEventsPerSecond / speed)
433     div = self._driver.ExecuteScript(
434         'document.body.innerHTML = "<div>old</div>";'
435         'var div = document.getElementsByTagName("div")[0];'
436         'div.addEventListener("touchstart", function() {'
437         '  div.innerHTML = "preMove0";'
438         '});'
439         'div.addEventListener("touchmove", function() {'
440         '  res = div.innerHTML.match(/preMove(\d+)/);'
441         '  if (res != null) {'
442         '    div.innerHTML = "preMove" + (parseInt(res[1], 10) + 1);'
443         '  }'
444         '});'
445         'div.addEventListener("touchend", function() {'
446         '  if (div.innerHTML == "preMove' + str(moveEvents) + '") {'
447         '    div.innerHTML = "new<br>";'
448         '  }'
449         '});'
450         'return div;')
451     self._driver.TouchFlick(div, dx, dy, speed)
452     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
453
454   def testTouchMovedElement(self):
455     div = self._driver.ExecuteScript(
456         'document.body.innerHTML = "<div>old</div>";'
457         'var div = document.getElementsByTagName("div")[0];'
458         'div.addEventListener("touchmove", function() {'
459         '  div.innerHTML="new<br>";'
460         '});'
461         'return div;')
462     loc = div.GetLocation()
463     self._driver.TouchDown(loc['x'], loc['y'])
464     self._driver.TouchMove(loc['x'] + 1, loc['y'] + 1)
465     self._driver.TouchUp(loc['x'] + 1, loc['y'] + 1)
466     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
467
468   def testClickElementInSubFrame(self):
469     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/frame_test.html'))
470     frame = self._driver.FindElement('tag name', 'iframe')
471     self._driver.SwitchToFrame(frame)
472     # Test clicking element in the sub frame.
473     self.testClickElement()
474
475   def testClearElement(self):
476     text = self._driver.ExecuteScript(
477         'document.body.innerHTML = \'<input type="text" value="abc">\';'
478         'var input = document.getElementsByTagName("input")[0];'
479         'input.addEventListener("change", function() {'
480         '  document.body.appendChild(document.createElement("br"));'
481         '});'
482         'return input;')
483     text.Clear()
484     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
485
486   def testSendKeysToElement(self):
487     text = self._driver.ExecuteScript(
488         'document.body.innerHTML = \'<input type="text">\';'
489         'var input = document.getElementsByTagName("input")[0];'
490         'input.addEventListener("change", function() {'
491         '  document.body.appendChild(document.createElement("br"));'
492         '});'
493         'return input;')
494     text.SendKeys('0123456789+-*/ Hi')
495     text.SendKeys(', there!')
496     value = self._driver.ExecuteScript('return arguments[0].value;', text)
497     self.assertEquals('0123456789+-*/ Hi, there!', value)
498
499   def testGetCurrentUrl(self):
500     self.assertEquals('data:,', self._driver.GetCurrentUrl())
501
502   def testGoBackAndGoForward(self):
503     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
504     self._driver.GoBack()
505     self._driver.GoForward()
506
507   def testRefresh(self):
508     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
509     self._driver.Refresh()
510
511   def testMouseMoveTo(self):
512     div = self._driver.ExecuteScript(
513         'document.body.innerHTML = "<div>old</div>";'
514         'var div = document.getElementsByTagName("div")[0];'
515         'div.style["width"] = "100px";'
516         'div.style["height"] = "100px";'
517         'div.addEventListener("mouseover", function() {'
518         '  var div = document.getElementsByTagName("div")[0];'
519         '  div.innerHTML="new<br>";'
520         '});'
521         'return div;')
522     self._driver.MouseMoveTo(div, 10, 10)
523     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
524
525   def testMouseClick(self):
526     div = self._driver.ExecuteScript(
527         'document.body.innerHTML = "<div>old</div>";'
528         'var div = document.getElementsByTagName("div")[0];'
529         'div.style["width"] = "100px";'
530         'div.style["height"] = "100px";'
531         'div.addEventListener("click", function() {'
532         '  var div = document.getElementsByTagName("div")[0];'
533         '  div.innerHTML="new<br>";'
534         '});'
535         'return div;')
536     self._driver.MouseMoveTo(div)
537     self._driver.MouseClick()
538     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
539
540   def testMouseButtonDownAndUp(self):
541     self._driver.ExecuteScript(
542         'document.body.innerHTML = "<div>old</div>";'
543         'var div = document.getElementsByTagName("div")[0];'
544         'div.style["width"] = "100px";'
545         'div.style["height"] = "100px";'
546         'div.addEventListener("mousedown", function() {'
547         '  var div = document.getElementsByTagName("div")[0];'
548         '  div.innerHTML="new1<br>";'
549         '});'
550         'div.addEventListener("mouseup", function() {'
551         '  var div = document.getElementsByTagName("div")[0];'
552         '  div.innerHTML="new2<a></a>";'
553         '});')
554     self._driver.MouseMoveTo(None, 50, 50)
555     self._driver.MouseButtonDown()
556     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
557     self._driver.MouseButtonUp()
558     self.assertEquals(1, len(self._driver.FindElements('tag name', 'a')))
559
560   def testMouseDoubleClick(self):
561     div = self._driver.ExecuteScript(
562         'document.body.innerHTML = "<div>old</div>";'
563         'var div = document.getElementsByTagName("div")[0];'
564         'div.style["width"] = "100px";'
565         'div.style["height"] = "100px";'
566         'div.addEventListener("dblclick", function() {'
567         '  var div = document.getElementsByTagName("div")[0];'
568         '  div.innerHTML="new<br>";'
569         '});'
570         'return div;')
571     self._driver.MouseMoveTo(div, 1, 1)
572     self._driver.MouseDoubleClick()
573     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
574
575   def testAlert(self):
576     self.assertFalse(self._driver.IsAlertOpen())
577     self._driver.ExecuteScript(
578         'window.setTimeout('
579         '    function() { window.confirmed = confirm(\'HI\'); },'
580         '    0);')
581     self.assertTrue(self._driver.IsAlertOpen())
582     self.assertEquals('HI', self._driver.GetAlertMessage())
583     self._driver.HandleAlert(False)
584     self.assertFalse(self._driver.IsAlertOpen())
585     self.assertEquals(False,
586                       self._driver.ExecuteScript('return window.confirmed'))
587
588   def testShouldHandleNewWindowLoadingProperly(self):
589     """Tests that ChromeDriver determines loading correctly for new windows."""
590     self._http_server.SetDataForPath(
591         '/newwindow',
592         """
593         <html>
594         <body>
595         <a href='%s' target='_blank'>new window/tab</a>
596         </body>
597         </html>""" % self._sync_server.GetUrl())
598     self._driver.Load(self._http_server.GetUrl() + '/newwindow')
599     old_windows = self._driver.GetWindowHandles()
600     self._driver.FindElement('tagName', 'a').Click()
601     new_window = self._WaitForNewWindow(old_windows)
602     self.assertNotEqual(None, new_window)
603
604     self.assertFalse(self._driver.IsLoading())
605     self._driver.SwitchToWindow(new_window)
606     self.assertTrue(self._driver.IsLoading())
607     self._sync_server.RespondWithContent('<html>new window</html>')
608     self._driver.ExecuteScript('return 1')  # Shouldn't hang.
609
610   def testPopups(self):
611     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
612     old_handles = self._driver.GetWindowHandles()
613     self._driver.ExecuteScript('window.open("about:blank")')
614     new_window_handle = self._WaitForNewWindow(old_handles)
615     self.assertNotEqual(None, new_window_handle)
616
617   def testNoSuchFrame(self):
618     self.assertRaises(chromedriver.NoSuchFrame,
619                       self._driver.SwitchToFrame, 'nosuchframe')
620     self.assertRaises(chromedriver.NoSuchFrame,
621                       self._driver.SwitchToFrame,
622                       self._driver.FindElement('tagName', 'body'))
623
624   def testWindowPosition(self):
625     position = self._driver.GetWindowPosition()
626     self._driver.SetWindowPosition(position[0], position[1])
627     self.assertEquals(position, self._driver.GetWindowPosition())
628
629     # Resize so the window isn't moved offscreen.
630     # See https://code.google.com/p/chromedriver/issues/detail?id=297.
631     self._driver.SetWindowSize(300, 300)
632
633     self._driver.SetWindowPosition(100, 200)
634     self.assertEquals([100, 200], self._driver.GetWindowPosition())
635
636   def testWindowSize(self):
637     size = self._driver.GetWindowSize()
638     self._driver.SetWindowSize(size[0], size[1])
639     self.assertEquals(size, self._driver.GetWindowSize())
640
641     self._driver.SetWindowSize(600, 400)
642     self.assertEquals([600, 400], self._driver.GetWindowSize())
643
644   def testWindowMaximize(self):
645     self._driver.SetWindowPosition(100, 200)
646     self._driver.SetWindowSize(600, 400)
647     self._driver.MaximizeWindow()
648
649     self.assertNotEqual([100, 200], self._driver.GetWindowPosition())
650     self.assertNotEqual([600, 400], self._driver.GetWindowSize())
651     # Set size first so that the window isn't moved offscreen.
652     # See https://code.google.com/p/chromedriver/issues/detail?id=297.
653     self._driver.SetWindowSize(600, 400)
654     self._driver.SetWindowPosition(100, 200)
655     self.assertEquals([100, 200], self._driver.GetWindowPosition())
656     self.assertEquals([600, 400], self._driver.GetWindowSize())
657
658   def testConsoleLogSources(self):
659     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/console_log.html'))
660     logs = self._driver.GetLog('browser')
661     self.assertEquals(len(logs), 2)
662     self.assertEquals(logs[0]['source'], 'network')
663     self.assertEquals(logs[1]['source'], 'javascript')
664
665   def testAutoReporting(self):
666     self.assertFalse(self._driver.IsAutoReporting())
667     self._driver.SetAutoReporting(True)
668     self.assertTrue(self._driver.IsAutoReporting())
669     url = self.GetHttpUrlForFile('/chromedriver/console_log.html')
670     self.assertRaisesRegexp(chromedriver.UnknownError,
671                             '.*(404|Failed to load resource).*',
672                             self._driver.Load,
673                             url)
674
675   def testContextMenuEventFired(self):
676     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/context_menu.html'))
677     self._driver.MouseMoveTo(self._driver.FindElement('tagName', 'div'))
678     self._driver.MouseClick(2)
679     self.assertTrue(self._driver.ExecuteScript('return success'))
680
681   def testHasFocusOnStartup(self):
682     # Some pages (about:blank) cause Chrome to put the focus in URL bar.
683     # This breaks tests depending on focus.
684     self.assertTrue(self._driver.ExecuteScript('return document.hasFocus()'))
685
686   def testTabCrash(self):
687     # If a tab is crashed, the session will be deleted.
688     # When 31 is released, will reload the tab instead.
689     # https://code.google.com/p/chromedriver/issues/detail?id=547
690     self.assertRaises(chromedriver.UnknownError,
691                       self._driver.Load, 'chrome://crash')
692     self.assertRaises(chromedriver.NoSuchSession,
693                       self._driver.GetCurrentUrl)
694
695   def testDoesntHangOnDebugger(self):
696     self._driver.ExecuteScript('debugger;')
697
698
699 class ChromeDriverAndroidTest(ChromeDriverBaseTest):
700   """End to end tests for Android-specific tests."""
701
702   def testLatestAndroidAppInstalled(self):
703     if ('stable' not in _ANDROID_PACKAGE_KEY and
704         'beta' not in _ANDROID_PACKAGE_KEY):
705       return
706
707     self._driver = self.CreateDriver()
708
709     try:
710       omaha_list = json.loads(
711           urllib2.urlopen('http://omahaproxy.appspot.com/all.json').read())
712       for l in omaha_list:
713         if l['os'] != 'android':
714           continue
715         for v in l['versions']:
716           if (('stable' in v['channel'] and 'stable' in _ANDROID_PACKAGE_KEY) or
717               ('beta' in v['channel'] and 'beta' in _ANDROID_PACKAGE_KEY)):
718             self.assertEquals(v['version'],
719                               self._driver.capabilities['version'])
720             return
721       raise RuntimeError('Malformed omaha JSON')
722     except urllib2.URLError as e:
723       print 'Unable to fetch current version info from omahaproxy (%s)' % e
724
725   def testDeviceManagement(self):
726     self._drivers = [self.CreateDriver() for x in
727                      android_commands.GetAttachedDevices()]
728     self.assertRaises(chromedriver.UnknownError, self.CreateDriver)
729     self._drivers[0].Quit()
730     self._drivers[0] = self.CreateDriver()
731
732
733 class ChromeSwitchesCapabilityTest(ChromeDriverBaseTest):
734   """Tests that chromedriver properly processes chromeOptions.args capabilities.
735
736   Makes sure the switches are passed to Chrome.
737   """
738
739   def testSwitchWithoutArgument(self):
740     """Tests that switch --dom-automation can be passed to Chrome.
741
742     Unless --dom-automation is specified, window.domAutomationController
743     is undefined.
744     """
745     driver = self.CreateDriver(chrome_switches=['dom-automation'])
746     self.assertNotEqual(
747         None,
748         driver.ExecuteScript('return window.domAutomationController'))
749
750
751 class ChromeExtensionsCapabilityTest(ChromeDriverBaseTest):
752   """Tests that chromedriver properly processes chromeOptions.extensions."""
753
754   def _PackExtension(self, ext_path):
755     return base64.b64encode(open(ext_path, 'rb').read())
756
757   def testExtensionsInstall(self):
758     """Checks that chromedriver can take the extensions."""
759     crx_1 = os.path.join(_TEST_DATA_DIR, 'ext_test_1.crx')
760     crx_2 = os.path.join(_TEST_DATA_DIR, 'ext_test_2.crx')
761     self.CreateDriver(chrome_extensions=[self._PackExtension(crx_1),
762                                          self._PackExtension(crx_2)])
763
764   def testWaitsForExtensionToLoad(self):
765     did_load_event = threading.Event()
766     server = webserver.SyncWebServer()
767     def RunServer():
768       time.sleep(5)
769       server.RespondWithContent('<html>iframe</html>')
770       did_load_event.set()
771
772     thread = threading.Thread(target=RunServer)
773     thread.daemon = True
774     thread.start()
775     crx = os.path.join(_TEST_DATA_DIR, 'ext_slow_loader.crx')
776     driver = self.CreateDriver(
777         chrome_switches=['user-agent=' + server.GetUrl()],
778         chrome_extensions=[self._PackExtension(crx)])
779     self.assertTrue(did_load_event.is_set())
780
781
782 class ChromeLogPathCapabilityTest(ChromeDriverBaseTest):
783   """Tests that chromedriver properly processes chromeOptions.logPath."""
784
785   LOG_MESSAGE = 'Welcome to ChromeLogPathCapabilityTest!'
786
787   def testChromeLogPath(self):
788     """Checks that user can specify the path of the chrome log.
789
790     Verifies that a log message is written into the specified log file.
791     """
792     tmp_log_path = tempfile.NamedTemporaryFile()
793     driver = self.CreateDriver(chrome_log_path=tmp_log_path.name)
794     driver.ExecuteScript('console.info("%s")' % self.LOG_MESSAGE)
795     driver.Quit()
796     self.assertTrue(self.LOG_MESSAGE in open(tmp_log_path.name).read())
797
798
799 class ChromeDriverLogTest(unittest.TestCase):
800   """Tests that chromedriver produces the expected log file."""
801
802   UNEXPECTED_CHROMEOPTION_CAP = 'unexpected_chromeoption_capability'
803   LOG_MESSAGE = 'unrecognized chrome option: %s' % UNEXPECTED_CHROMEOPTION_CAP
804
805   def testChromeDriverLog(self):
806     _, tmp_log_path = tempfile.mkstemp(prefix='chromedriver_log_')
807     chromedriver_server = server.Server(
808         _CHROMEDRIVER_BINARY, log_path=tmp_log_path)
809     try:
810       driver = chromedriver.ChromeDriver(
811           chromedriver_server.GetUrl(), chrome_binary=_CHROME_BINARY,
812           experimental_options={ self.UNEXPECTED_CHROMEOPTION_CAP : 1 })
813       driver.Quit()
814     except chromedriver.ChromeDriverException, e:
815       self.assertTrue(self.LOG_MESSAGE in e.message)
816     finally:
817       chromedriver_server.Kill()
818     with open(tmp_log_path, 'r') as f:
819       self.assertTrue(self.LOG_MESSAGE in f.read())
820
821
822 class SessionHandlingTest(ChromeDriverBaseTest):
823   """Tests for session operations."""
824   def testQuitASessionMoreThanOnce(self):
825     driver = self.CreateDriver()
826     driver.Quit()
827     driver.Quit()
828
829
830 class ExistingBrowserTest(ChromeDriverBaseTest):
831   """Tests for ChromeDriver existing browser capability."""
832   def setUp(self):
833     self.assertTrue(_CHROME_BINARY is not None,
834                     'must supply a chrome binary arg')
835
836   def testConnectToExistingBrowser(self):
837     port = self.FindFreePort()
838     temp_dir = util.MakeTempDir()
839     process = subprocess.Popen([_CHROME_BINARY,
840                                 '--remote-debugging-port=%d' % port,
841                                 '--user-data-dir=%s' % temp_dir])
842     if process is None:
843       raise RuntimeError('Chrome could not be started with debugging port')
844     try:
845       driver = self.CreateDriver(debugger_address='127.0.0.1:%d' % port)
846       driver.ExecuteScript('console.info("%s")' % 'connecting at %d!' % port)
847       driver.Quit()
848     finally:
849       process.terminate()
850
851   def FindFreePort(self):
852     for port in range(10000, 10100):
853       try:
854         socket.create_connection(('127.0.0.1', port), 0.2).close()
855       except socket.error:
856         return port
857     raise RuntimeError('Cannot find open port')
858
859 class PerfTest(ChromeDriverBaseTest):
860   """Tests for ChromeDriver perf."""
861   def setUp(self):
862     self.assertTrue(_REFERENCE_CHROMEDRIVER is not None,
863                     'must supply a reference-chromedriver arg')
864
865   def _RunDriverPerfTest(self, name, test_func):
866     """Runs a perf test comparing a reference and new ChromeDriver server.
867
868     Args:
869       name: The name of the perf test.
870       test_func: Called with the server url to perform the test action. Must
871                  return the time elapsed.
872     """
873     class Results(object):
874       ref = []
875       new = []
876
877     ref_server = server.Server(_REFERENCE_CHROMEDRIVER)
878     results = Results()
879     result_url_pairs = zip([results.new, results.ref],
880                            [_CHROMEDRIVER_SERVER_URL, ref_server.GetUrl()])
881     for iteration in range(30):
882       for result, url in result_url_pairs:
883         result += [test_func(url)]
884       # Reverse the order for the next run.
885       result_url_pairs = result_url_pairs[::-1]
886
887     def PrintResult(build, result):
888       mean = sum(result) / len(result)
889       avg_dev = sum([abs(sample - mean) for sample in result]) / len(result)
890       print 'perf result', build, name, mean, avg_dev, result
891       util.AddBuildStepText('%s %s: %.3f+-%.3f' % (
892           build, name, mean, avg_dev))
893
894     # Discard first result, which may be off due to cold start.
895     PrintResult('new', results.new[1:])
896     PrintResult('ref', results.ref[1:])
897
898   def testSessionStartTime(self):
899     def Run(url):
900       start = time.time()
901       driver = self.CreateDriver(url)
902       end = time.time()
903       driver.Quit()
904       return end - start
905     self._RunDriverPerfTest('session start', Run)
906
907   def testSessionStopTime(self):
908     def Run(url):
909       driver = self.CreateDriver(url)
910       start = time.time()
911       driver.Quit()
912       end = time.time()
913       return end - start
914     self._RunDriverPerfTest('session stop', Run)
915
916   def testColdExecuteScript(self):
917     def Run(url):
918       driver = self.CreateDriver(url)
919       start = time.time()
920       driver.ExecuteScript('return 1')
921       end = time.time()
922       driver.Quit()
923       return end - start
924     self._RunDriverPerfTest('cold exe js', Run)
925
926 if __name__ == '__main__':
927   parser = optparse.OptionParser()
928   parser.add_option(
929       '', '--chromedriver',
930       help='Path to chromedriver server (REQUIRED!)')
931   parser.add_option(
932       '', '--log-path',
933       help='Output verbose server logs to this file')
934   parser.add_option(
935       '', '--reference-chromedriver',
936       help='Path to the reference chromedriver server')
937   parser.add_option(
938       '', '--chrome', help='Path to a build of the chrome binary')
939   parser.add_option(
940       '', '--chrome-version', default='HEAD',
941       help='Version of chrome. Default is \'HEAD\'.')
942   parser.add_option(
943       '', '--filter', type='string', default='*',
944       help=('Filter for specifying what tests to run, "*" will run all. E.g., '
945             '*testStartStop'))
946   parser.add_option(
947       '', '--android-package',
948       help=('Android package key. Possible values: ' +
949             str(_ANDROID_NEGATIVE_FILTER.keys())))
950   options, args = parser.parse_args()
951
952   options.chromedriver = util.GetAbsolutePathOfUserPath(options.chromedriver)
953   if not options.chromedriver or not os.path.exists(options.chromedriver):
954     parser.error('chromedriver is required or the given path is invalid.' +
955                  'Please run "%s --help" for help' % __file__)
956
957   global _CHROMEDRIVER_BINARY
958   _CHROMEDRIVER_BINARY = options.chromedriver
959
960   if (options.android_package and
961       options.android_package not in _ANDROID_NEGATIVE_FILTER):
962     parser.error('Invalid --android-package')
963
964   chromedriver_server = server.Server(_CHROMEDRIVER_BINARY, options.log_path)
965   global _CHROMEDRIVER_SERVER_URL
966   _CHROMEDRIVER_SERVER_URL = chromedriver_server.GetUrl()
967
968   global _REFERENCE_CHROMEDRIVER
969   _REFERENCE_CHROMEDRIVER = util.GetAbsolutePathOfUserPath(
970       options.reference_chromedriver)
971
972   global _CHROME_BINARY
973   if options.chrome:
974     _CHROME_BINARY = util.GetAbsolutePathOfUserPath(options.chrome)
975   else:
976     _CHROME_BINARY = None
977
978   global _ANDROID_PACKAGE_KEY
979   _ANDROID_PACKAGE_KEY = options.android_package
980
981   if options.filter == '*':
982     if _ANDROID_PACKAGE_KEY:
983       negative_filter = _ANDROID_NEGATIVE_FILTER[_ANDROID_PACKAGE_KEY]
984     else:
985       negative_filter = _GetDesktopNegativeFilter(options.chrome_version)
986     options.filter = '*-' + ':__main__.'.join([''] + negative_filter)
987
988   all_tests_suite = unittest.defaultTestLoader.loadTestsFromModule(
989       sys.modules[__name__])
990   tests = unittest_util.FilterTestSuite(all_tests_suite, options.filter)
991   ChromeDriverTest.GlobalSetUp()
992   result = unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(tests)
993   ChromeDriverTest.GlobalTearDown()
994   sys.exit(len(result.failures) + len(result.errors))