Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webdriver / pylib / selenium / webdriver / remote / webdriver.py
1 # Copyright 2008-2011 WebDriver committers
2 # Copyright 2008-2011 Google Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 """
16 The WebDriver implementation.
17 """
18 import base64
19 from command import Command
20 from webelement import WebElement
21 from remote_connection import RemoteConnection
22 from errorhandler import ErrorHandler
23 from selenium.common.exceptions import WebDriverException
24 from selenium.common.exceptions import InvalidSelectorException
25 from selenium.webdriver.common.by import By
26 from selenium.webdriver.common.alert import Alert
27 from selenium.webdriver.common.html5.application_cache import ApplicationCache
28
29
30 class WebDriver(object):
31     """
32     Controls a browser by sending commands to a remote server.
33     This server is expected to be running the WebDriver wire protocol as defined
34     here: http://code.google.com/p/selenium/wiki/JsonWireProtocol
35
36     :Attributes:
37      - command_executor - The command.CommandExecutor object used to execute commands.
38      - error_handler - errorhandler.ErrorHandler object used to verify that the server did not return an error.
39      - session_id - The session ID to send with every command.
40      - capabilities - A dictionary of capabilities of the underlying browser for this instance's session.
41     """
42
43     def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub',
44         desired_capabilities=None, browser_profile=None):
45         """
46         Create a new driver that will issue commands using the wire protocol.
47
48         :Args:
49          - command_executor - Either a command.CommandExecutor object or a string that specifies the URL of a remote server to send commands to.
50          - desired_capabilities - Dictionary holding predefined values for starting a browser
51          - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object.  Only used if Firefox is requested.
52         """
53         if desired_capabilities is None:
54             raise WebDriverException("Desired Capabilities can't be None")
55         if not isinstance(desired_capabilities, dict):
56             raise WebDriverException("Desired Capabilities must be a dictionary")
57         self.command_executor = command_executor
58         if type(self.command_executor) is str or type(self.command_executor) is unicode:
59             self.command_executor = RemoteConnection(command_executor)
60         self.session_id = None
61         self.capabilities = {}
62         self.error_handler = ErrorHandler()
63         self.start_client()
64         self.start_session(desired_capabilities, browser_profile)
65
66     @property
67     def name(self):
68         """Returns the name of the underlying browser for this instance.
69
70         :Usage:
71          - driver.name
72         """
73         if 'browserName' in self.capabilities:
74             return self.capabilities['browserName']
75         else:
76             raise KeyError('browserName not specified in session capabilities')
77
78     def start_client(self):
79         """
80         Called before starting a new session. This method may be overridden
81         to define custom startup behavior.
82         """
83         pass
84
85     def stop_client(self):
86         """
87         Called after executing a quit command. This method may be overridden
88         to define custom shutdown behavior.
89         """
90         pass
91
92     def start_session(self, desired_capabilities, browser_profile=None):
93         """
94         Creates a new session with the desired capabilities.
95
96         :Args:
97          - browser_name - The name of the browser to request.
98          - version - Which browser version to request.
99          - platform - Which platform to request the browser on.
100          - javascript_enabled - Whether the new session should support JavaScript.
101          - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested.
102         """
103         if browser_profile:
104             desired_capabilities['firefox_profile'] = browser_profile.encoded
105         response = self.execute(Command.NEW_SESSION, {
106             'desiredCapabilities': desired_capabilities,
107         })
108         self.session_id = response['sessionId']
109         self.capabilities = response['value']
110
111     def _wrap_value(self, value):
112         if isinstance(value, dict):
113             converted = {}
114             for key, val in value.items():
115                 converted[key] = self._wrap_value(val)
116             return converted
117         elif isinstance(value, WebElement):
118             return {'ELEMENT': value.id}
119         elif isinstance(value, list):
120             return list(self._wrap_value(item) for item in value)
121         else:
122             return value
123
124     def create_web_element(self, element_id):
125         """
126         Creates a web element with the specified element_id.
127         """
128         return WebElement(self, element_id)
129
130     def _unwrap_value(self, value):
131         if isinstance(value, dict) and 'ELEMENT' in value:
132             return self.create_web_element(value['ELEMENT'])
133         elif isinstance(value, list):
134             return list(self._unwrap_value(item) for item in value)
135         else:
136             return value
137
138     def execute(self, driver_command, params=None):
139         """
140         Sends a command to be executed by a command.CommandExecutor.
141
142         :Args:
143          - driver_command: The name of the command to execute as a string.
144          - params: A dictionary of named parameters to send with the command.
145
146         :Returns:
147           The command's JSON response loaded into a dictionary object.
148         """
149         if not params:
150             params = {'sessionId': self.session_id}
151         elif 'sessionId' not in params:
152             params['sessionId'] = self.session_id
153
154         params = self._wrap_value(params)
155         response = self.command_executor.execute(driver_command, params)
156         if response:
157             self.error_handler.check_response(response)
158             response['value'] = self._unwrap_value(
159                 response.get('value', None))
160             return response
161         # If the server doesn't send a response, assume the command was
162         # a success
163         return {'success': 0, 'value': None, 'sessionId': self.session_id}
164
165     def get(self, url):
166         """
167         Loads a web page in the current browser session.
168         """
169         self.execute(Command.GET, {'url': url})
170
171     @property
172     def title(self):
173         """Returns the title of the current page.
174
175         :Usage:
176             driver.title
177         """
178         resp = self.execute(Command.GET_TITLE)
179         return resp['value'] if resp['value'] is not None else ""
180
181     def find_element_by_id(self, id_):
182         """Finds an element by id.
183
184         :Args:
185          - id\_ - The id of the element to be found.
186
187         :Usage:
188             driver.find_element_by_id('foo')
189         """
190         return self.find_element(by=By.ID, value=id_)
191
192     def find_elements_by_id(self, id_):
193         """
194         Finds multiple elements by id.
195
196         :Args:
197          - id\_ - The id of the elements to be found.
198
199         :Usage:
200             driver.find_element_by_id('foo')
201         """
202         return self.find_elements(by=By.ID, value=id_)
203
204     def find_element_by_xpath(self, xpath):
205         """
206         Finds an element by xpath.
207
208         :Args:
209          - xpath - The xpath locator of the element to find.
210
211         :Usage:
212             driver.find_element_by_xpath('//div/td[1]')
213         """
214         return self.find_element(by=By.XPATH, value=xpath)
215
216     def find_elements_by_xpath(self, xpath):
217         """
218         Finds multiple elements by xpath.
219
220         :Args:
221          - xpath - The xpath locator of the elements to be found.
222
223         :Usage:
224             driver.find_elements_by_xpath("//div[contains(@class, 'foo')]")
225         """
226         return self.find_elements(by=By.XPATH, value=xpath)
227
228     def find_element_by_link_text(self, link_text):
229         """
230         Finds an element by link text.
231
232         :Args:
233          - link_text: The text of the element to be found.
234
235         :Usage:
236             driver.find_element_by_link_text('Sign In')
237         """
238         return self.find_element(by=By.LINK_TEXT, value=link_text)
239
240     def find_elements_by_link_text(self, text):
241         """
242         Finds elements by link text.
243
244         :Args:
245          - link_text: The text of the elements to be found.
246
247         :Usage:
248             driver.find_elements_by_link_text('Sign In')
249         """
250         return self.find_elements(by=By.LINK_TEXT, value=text)
251
252     def find_element_by_partial_link_text(self, link_text):
253         """
254         Finds an element by a partial match of its link text.
255
256         :Args:
257          - link_text: The text of the element to partially match on.
258
259         :Usage:
260             driver.find_element_by_partial_link_text('Sign')
261         """
262         return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text)
263
264     def find_elements_by_partial_link_text(self, link_text):
265         """
266         Finds elements by a partial match of their link text.
267
268         :Args:
269          - link_text: The text of the element to partial match on.
270
271         :Usage:
272             driver.find_element_by_partial_link_text('Sign')
273         """
274         return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text)
275
276     def find_element_by_name(self, name):
277         """
278         Finds an element by name.
279
280         :Args:
281          - name: The name of the element to find.
282
283         :Usage:
284             driver.find_element_by_name('foo')
285         """
286         return self.find_element(by=By.NAME, value=name)
287
288     def find_elements_by_name(self, name):
289         """
290         Finds elements by name.
291
292         :Args:
293          - name: The name of the elements to find.
294
295         :Usage:
296             driver.find_elements_by_name('foo')
297         """
298         return self.find_elements(by=By.NAME, value=name)
299
300     def find_element_by_tag_name(self, name):
301         """
302         Finds an element by tag name.
303
304         :Args:
305          - name: The tag name of the element to find.
306
307         :Usage:
308             driver.find_element_by_tag_name('foo')
309         """
310         return self.find_element(by=By.TAG_NAME, value=name)
311
312     def find_elements_by_tag_name(self, name):
313         """
314         Finds elements by tag name.
315
316         :Args:
317          - name: The tag name the use when finding elements.
318
319         :Usage:
320             driver.find_elements_by_tag_name('foo')
321         """
322         return self.find_elements(by=By.TAG_NAME, value=name)
323
324     def find_element_by_class_name(self, name):
325         """
326         Finds an element by class name.
327
328         :Args:
329          - name: The class name of the element to find.
330
331         :Usage:
332             driver.find_element_by_class_name('foo')
333         """
334         return self.find_element(by=By.CLASS_NAME, value=name)
335
336     def find_elements_by_class_name(self, name):
337         """
338         Finds elements by class name.
339
340         :Args:
341          - name: The class name of the elements to find.
342
343         :Usage:
344             driver.find_elements_by_class_name('foo')
345         """
346         return self.find_elements(by=By.CLASS_NAME, value=name)
347
348     def find_element_by_css_selector(self, css_selector):
349         """
350         Finds an element by css selector.
351
352         :Args:
353          - css_selector: The css selector to use when finding elements.
354
355         :Usage:
356             driver.find_element_by_css_selector('#foo')
357         """
358         return self.find_element(by=By.CSS_SELECTOR, value=css_selector)
359
360     def find_elements_by_css_selector(self, css_selector):
361         """
362         Finds elements by css selector.
363
364         :Args:
365          - css_selector: The css selector to use when finding elements.
366
367         :Usage:
368             driver.find_element_by_css_selector('#foo')
369         """
370         return self.find_elements(by=By.CSS_SELECTOR, value=css_selector)
371
372     def execute_script(self, script, *args):
373         """
374         Synchronously Executes JavaScript in the current window/frame.
375
376         :Args:
377          - script: The JavaScript to execute.
378          - \*args: Any applicable arguments for your JavaScript.
379
380         :Usage:
381             driver.execute_script('document.title')
382         """
383         if len(args) == 1:
384             converted_args = args[0]
385         else:
386             converted_args = list(args)
387         converted_args = list(args)
388         return self.execute(Command.EXECUTE_SCRIPT,
389             {'script': script, 'args':converted_args})['value']
390
391     def execute_async_script(self, script, *args):
392         """
393         Asynchronously Executes JavaScript in the current window/frame.
394
395         :Args:
396          - script: The JavaScript to execute.
397          - \*args: Any applicable arguments for your JavaScript.
398
399         :Usage:
400             driver.execute_async_script('document.title')
401         """
402         if len(args) == 1:
403             converted_args = args[0]
404         else:
405             converted_args = list(args)
406         converted_args = list(args)
407         return self.execute(Command.EXECUTE_ASYNC_SCRIPT,
408             {'script': script, 'args':converted_args})['value']
409
410     @property
411     def current_url(self):
412         """
413         Gets the URL of the current page.
414
415         :Usage:
416             driver.current_url
417         """
418         return self.execute(Command.GET_CURRENT_URL)['value']
419
420     @property
421     def page_source(self):
422         """
423         Gets the source of the current page.
424
425         :Usage:
426             driver.page_source
427         """
428         return self.execute(Command.GET_PAGE_SOURCE)['value']
429
430     def close(self):
431         """
432         Closes the current window.
433
434         :Usage:
435             driver.close()
436         """
437         self.execute(Command.CLOSE)
438
439     def quit(self):
440         """
441         Quits the driver and closes every associated window.
442
443         :Usage:
444             driver.quit()
445         """
446         try:
447             self.execute(Command.QUIT)
448         finally:
449             self.stop_client()
450
451     @property
452     def current_window_handle(self):
453         """
454         Returns the handle of the current window.
455
456         :Usage:
457             driver.current_window_handle
458         """
459         return self.execute(Command.GET_CURRENT_WINDOW_HANDLE)['value']
460
461     @property
462     def window_handles(self):
463         """
464         Returns the handles of all windows within the current session.
465
466         :Usage:
467             driver.window_handles
468         """
469         return self.execute(Command.GET_WINDOW_HANDLES)['value']
470
471     def maximize_window(self):
472         """
473         Maximizes the current window that webdriver is using
474         """
475         self.execute(Command.MAXIMIZE_WINDOW, {"windowHandle": "current"})
476
477     #Target Locators
478     def switch_to_active_element(self):
479         """
480         Returns the element with focus, or BODY if nothing has focus.
481
482         :Usage:
483             driver.switch_to_active_element()
484         """
485         return self.execute(Command.GET_ACTIVE_ELEMENT)['value']
486
487     def switch_to_window(self, window_name):
488         """
489         Switches focus to the specified window.
490
491         :Args:
492          - window_name: The name or window handle of the window to switch to.
493
494         :Usage:
495             driver.switch_to_window('main')
496         """
497         self.execute(Command.SWITCH_TO_WINDOW, {'name': window_name})
498
499     def switch_to_frame(self, frame_reference):
500         """
501         Switches focus to the specified frame, by index, name, or webelement.
502
503         :Args:
504          - frame_reference: The name of the window to switch to, an integer representing the index,
505                             or a webelement that is an (i)frame to switch to.
506
507         :Usage:
508             driver.switch_to_frame('frame_name')
509             driver.switch_to_frame(1)
510             driver.switch_to_frame(driver.find_elements_by_tag_name("iframe")[0])
511         """
512         self.execute(Command.SWITCH_TO_FRAME, {'id': frame_reference})
513
514     def switch_to_default_content(self):
515         """
516         Switch focus to the default frame.
517
518         :Usage:
519             driver.switch_to_default_content()
520         """
521         self.execute(Command.SWITCH_TO_FRAME, {'id': None})
522
523     def switch_to_alert(self):
524         """
525         Switches focus to an alert on the page.
526
527         :Usage:
528             driver.switch_to_alert()
529         """
530         return Alert(self)
531
532     #Navigation
533     def back(self):
534         """
535         Goes one step backward in the browser history.
536
537         :Usage:
538             driver.back()
539         """
540         self.execute(Command.GO_BACK)
541
542     def forward(self):
543         """
544         Goes one step forward in the browser history.
545
546         :Usage:
547             driver.forward()
548         """
549         self.execute(Command.GO_FORWARD)
550
551     def refresh(self):
552         """
553         Refreshes the current page.
554
555         :Usage:
556             driver.refresh()
557         """
558         self.execute(Command.REFRESH)
559
560     # Options
561     def get_cookies(self):
562         """
563         Returns a set of dictionaries, corresponding to cookies visible in the current session.
564
565         :Usage:
566             driver.get_cookies()
567         """
568         return self.execute(Command.GET_ALL_COOKIES)['value']
569
570     def get_cookie(self, name):
571         """
572         Get a single cookie by name. Returns the cookie if found, None if not.
573
574         :Usage:
575             driver.get_cookie('my_cookie')
576         """
577         cookies = self.get_cookies()
578         for cookie in cookies:
579             if cookie['name'] == name:
580                 return cookie
581         return None
582
583     def delete_cookie(self, name):
584         """
585         Deletes a single cookie with the given name.
586
587         :Usage:
588             driver.delete_cookie('my_cookie')
589         """
590         self.execute(Command.DELETE_COOKIE, {'name': name})
591
592     def delete_all_cookies(self):
593         """
594         Delete all cookies in the scope of the session.
595
596         :Usage:
597             driver.delete_all_cookies()
598         """
599         self.execute(Command.DELETE_ALL_COOKIES)
600
601     def add_cookie(self, cookie_dict):
602         """
603         Adds a cookie to your current session.
604
605         :Args:
606          - cookie_dict: A dictionary object, with required keys - "name" and "value";
607             optional keys - "path", "domain", "secure", "expiry"
608
609         Usage:
610             driver.add_cookie({'name' : 'foo', 'value' : 'bar'})
611             driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/'})
612             driver.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/', 'secure':True})
613
614         """
615         self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict})
616
617     # Timeouts
618     def implicitly_wait(self, time_to_wait):
619         """
620         Sets a sticky timeout to implicitly wait for an element to be found,
621            or a command to complete. This method only needs to be called one
622            time per session. To set the timeout for calls to
623            execute_async_script, see set_script_timeout.
624
625         :Args:
626          - time_to_wait: Amount of time to wait (in seconds)
627
628         :Usage:
629             driver.implicitly_wait(30)
630         """
631         self.execute(Command.IMPLICIT_WAIT, {'ms': float(time_to_wait) * 1000})
632
633     def set_script_timeout(self, time_to_wait):
634         """
635         Set the amount of time that the script should wait during an
636            execute_async_script call before throwing an error.
637
638         :Args:
639          - time_to_wait: The amount of time to wait (in seconds)
640
641         :Usage:
642             driver.set_script_timeout(30)
643         """
644         self.execute(Command.SET_SCRIPT_TIMEOUT,
645             {'ms': float(time_to_wait) * 1000})
646
647     def set_page_load_timeout(self, time_to_wait):
648         """
649         Set the amount of time to wait for a page load to complete 
650            before throwing an error.
651
652         :Args:
653          - time_to_wait: The amount of time to wait
654
655         :Usage:
656             driver.set_page_load_timeout(30)
657         """
658         self.execute(Command.SET_TIMEOUTS,
659             {'ms': float(time_to_wait) * 1000, 'type':'page load'})
660
661     def find_element(self, by=By.ID, value=None):
662         """
663         'Private' method used by the find_element_by_* methods.
664
665         :Usage:
666             Use the corresponding find_element_by_* instead of this.
667         """
668         if isinstance(by, tuple) or isinstance(value, int) or value==None:
669             raise InvalidSelectorException("Invalid locator values passed in")
670             
671         return self.execute(Command.FIND_ELEMENT,
672                              {'using': by, 'value': value})['value']
673
674     def find_elements(self, by=By.ID, value=None):
675         """
676         'Private' method used by the find_elements_by_* methods.
677
678         :Usage:
679             Use the corresponding find_elements_by_* instead of this.
680         """
681         if isinstance(by, tuple) or isinstance(value, int) or value==None:
682             raise InvalidSelectorException("Invalid locator values passed in")
683
684         return self.execute(Command.FIND_ELEMENTS,
685                              {'using': by, 'value': value})['value']
686     @property
687     def desired_capabilities(self):
688         """
689         returns the drivers current desired capabilities being used
690         """
691         return self.capabilities
692
693     def get_screenshot_as_file(self, filename):
694         """
695         Gets the screenshot of the current window. Returns False if there is
696            any IOError, else returns True. Use full paths in your filename.
697
698         :Args:
699          - filename: The full path you wish to save your screenshot to.
700
701         :Usage:
702             driver.get_screenshot_as_file('/Screenshots/foo.png')
703         """
704         png = self.execute(Command.SCREENSHOT)['value']
705         try:
706             with open(filename, 'wb') as f:
707                 f.write(base64.decodestring(png))
708         except IOError:
709             return False
710         del png
711         return True
712
713     def get_screenshot_as_base64(self):
714         """
715         Gets the screenshot of the current window as a base64 encoded string
716            which is useful in embedded images in HTML.
717
718         :Usage:
719             driver.get_screenshot_as_base64()
720         """
721         return self.execute(Command.SCREENSHOT)['value']
722
723     def set_window_size(self, width, height, windowHandle='current'):
724         """
725         Sets the width and height of the current window. (window.resizeTo)
726
727         :Args:
728          - width: the width in pixels to set the window to
729          - height: the height in pixels to set the window to
730
731         :Usage:
732             driver.set_window_size(800,600)
733         """
734         self.execute(Command.SET_WINDOW_SIZE, {'width': width, 'height': height,
735           'windowHandle': windowHandle})
736
737     def get_window_size(self, windowHandle='current'):
738         """
739         Gets the width and height of the current window.
740
741         :Usage:
742             driver.get_window_size()
743         """
744         return self.execute(Command.GET_WINDOW_SIZE,
745             {'windowHandle': windowHandle})['value']
746
747     def set_window_position(self, x, y, windowHandle='current'):
748         """
749         Sets the x,y position of the current window. (window.moveTo)
750
751         :Args:
752          - x: the x-coordinate in pixels to set the window position
753          - y: the y-coordinate in pixels to set the window position
754
755         :Usage:
756             driver.set_window_position(0,0)
757         """
758         self.execute(Command.SET_WINDOW_POSITION, {'x': x, 'y': y,
759           'windowHandle': windowHandle})
760
761     def get_window_position(self, windowHandle='current'):
762         """
763         Gets the x,y position of the current window.
764
765         :Usage:
766             driver.get_window_position()
767         """
768         return self.execute(Command.GET_WINDOW_POSITION,
769             {'windowHandle': windowHandle})['value']
770
771     @property
772     def orientation(self):
773         """
774         Gets the current orientation of the device
775
776         :Usage:
777             orientation = driver.orientation
778         """
779         return self.execute(Command.GET_SCREEN_ORIENTATION)['value']
780
781     @orientation.setter
782     def orientation(self, value):
783         """
784         Sets the current orientation of the device
785
786         :Args:
787          - value: orientation to set it to.
788
789         :Usage:
790             driver.orientation = 'landscape'
791         """
792         allowed_values = ['LANDSCAPE', 'PORTRAIT']
793         if value.upper() in allowed_values:
794             self.execute(Command.SET_SCREEN_ORIENTATION, {'orientation': value})['value']
795         else:
796             raise WebDriverException("You can only set the orientation to 'LANDSCAPE' and 'PORTRAIT'")
797
798     def is_online(self):
799         """ Returns a boolean if the browser is online or offline"""
800         return self.execute(Command.IS_BROWSER_ONLINE)['value']
801
802     @property
803     def application_cache(self):
804         """ Returns a ApplicationCache Object to interact with the browser app cache"""
805         return ApplicationCache(self)
806
807     def save_screenshot(self, filename):
808         """
809         Gets the screenshot of the current window. Returns False if there is
810         any IOError, else returns True. Use full paths in your filename.
811         """
812         png = self.execute(Command.SCREENSHOT)['value']
813         try:
814             f = open(filename, 'wb')
815             f.write(base64.decodestring(png))
816             f.close()
817         except IOError:
818             return False
819         finally:
820             del png
821         return True