15817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
25817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng# Use of this source code is governed by a BSD-style license that can be
35817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng# found in the LICENSE file.
45817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
55817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng"""The classes for web elements on a page."""
65817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
75817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng__author__ = 'cliffordcheng@google.com (Clifford Cheng)'
85817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
95817c231041fd60368e31ca80f18a09b0cc1d289Clifford Chengimport re
105817c231041fd60368e31ca80f18a09b0cc1d289Clifford Chengfrom selenium.webdriver.common.keys import Keys
115817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
125817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
135817c231041fd60368e31ca80f18a09b0cc1d289Clifford Chengclass WebElements(object):
145817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng  """The base class for all the web element controls."""
155817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
165817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng  def __init__(self, driver, element_id, name=None):
175817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      """Constructor."""
185817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      self._driver = driver
195817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      self._element_id = element_id
205817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      self._name = name
215817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      self._element = driver.find_element_by_id(element_id)
225817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
235817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
245817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng  def get_name(self):
255817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      """
265817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      Returns the name of a web element.
275817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
285817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      @return The name of a web element
295817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      """
305817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      return self._name
315817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
325817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
335817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng  def get_element_id(self):
345817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      """
355817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      Returns the element ID of a web element.
365817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
375817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      @return The element ID of a web element
385817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      """
395817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      return self._element_id
405817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
415817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
425817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng  def get_element(self):
435817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      """
445817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      Returns the object of a web element.
455817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
465817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      @return The web element object
475817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      """
485817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng      return self._element
495817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
505817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
515817c231041fd60368e31ca80f18a09b0cc1d289Clifford Chengclass TextBox(WebElements):
525817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    """Web element textbox and its controls."""
535817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
545817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
555817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    def get_value(self):
565817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
575817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        Returns the value in the text box.
585817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
595817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        @return The value in the text box
605817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
615817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        return self._element.get_attribute('value')
625817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
635817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
645817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    def set_value(self, value):
655817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
665817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        Set a value in the text box.
675817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
685817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        @param value: The value to be set in the text box
695817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        @raises RuntimeError if an error occurred when setting values
705817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
71ea1f3c7f320e6b7d54358c0692d6e35511e36056Clifford Cheng        # Using backspace instead of clear() because of crbug/450812
72ea1f3c7f320e6b7d54358c0692d6e35511e36056Clifford Cheng        # TODO(cliffordcheng): Revert this once the bug is fixed
73ea1f3c7f320e6b7d54358c0692d6e35511e36056Clifford Cheng        original_value = self._element.get_attribute('value')
74ea1f3c7f320e6b7d54358c0692d6e35511e36056Clifford Cheng        for i in range(len(original_value)):
75ea1f3c7f320e6b7d54358c0692d6e35511e36056Clifford Cheng            self._element.send_keys('\b')
765817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        self._element.send_keys(value)
775817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        if self.get_value() != value:
785817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng            raise RuntimeError(
795817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng                    'Failed to set value "%s"', self._element.get_name())
805817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
815817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
825817c231041fd60368e31ca80f18a09b0cc1d289Clifford Chengclass Button(WebElements):
835817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    """Web element button and its controls."""
845817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
855817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    def click(self):
865817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
875817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        Click on the button.
885817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
895817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        self._element.click()
905817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
915817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
925817c231041fd60368e31ca80f18a09b0cc1d289Clifford Chengclass CheckBox(WebElements):
935817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    """Web element checbkbox and its controls."""
945817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
955817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    def set_value(self, value):
965817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
975817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        Set a value in the check box.
985817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
995817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        @param value: The value ('on'/'off') to be set in the check box
1005817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
1015817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        if value == 'on' and not self.get_value():
1025817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng              self._element.click()
1035817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        elif value == 'off' and self.get_value():
1045817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng              self._element.click()
1055817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1065817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1075817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    def get_value(self):
1085817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
1095817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        Return the value of the check box.
1105817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1115817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        @return True if the check box is checked, otherwise return False.
1125817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
1135817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        return self._element.is_selected()
1145817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1155817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1165817c231041fd60368e31ca80f18a09b0cc1d289Clifford Chengclass RadioButton(WebElements):
1175817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    """Web element radio button and its controls."""
1185817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1195817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    def click(self):
1205817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """Click the radio button."""
1215817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        self._element.send_keys(Keys.SPACE)
1225817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        # Click one more time to ensure it's clicked
1235817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        # In some corner cases, it needs a second click
1245817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        self._element.send_keys(Keys.SPACE)
1255817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1265817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1275817c231041fd60368e31ca80f18a09b0cc1d289Clifford Chengclass ScrollBox(WebElements):
1285817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    """Web element scroll box and its controls."""
1295817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1305817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    def get_value(self):
1315817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
1325817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        Return the text in the scroll box.
1335817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1345817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        @return The string in the scroll box
1355817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
1365817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        get_inner_html = 'return document.getElementById("%s").innerHTML;'
1375817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        get_inner_html %= self._element_id
1385817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        inner_html = self._driver.execute_script(get_inner_html)
1395817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        inner_text_search = re.search('<.*>(.*)<.*>', inner_html)
1405817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        try:
1415817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng            return inner_text_search.group(1)
1425817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        except AttributeError:
1435817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng            return None
1445817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1455817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1465817c231041fd60368e31ca80f18a09b0cc1d289Clifford Chengclass WebElementBox(WebElements):
1475817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    """Web element box and its controls."""
1485817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1495817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng    def get_value(self):
1505817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
1515817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        Return the text in the web element box.
1525817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng
1535817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        @return The string in the web element box
1545817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        """
1555817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        get_inner_html = 'return document.getElementById("%s").innerHTML;'
1565817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        get_inner_html %= self._element_id
1575817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        inner_html = self._driver.execute_script(get_inner_html)
1585817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        inner_text_search = re.search('<.*>(.*)<.*>', inner_html)
1595817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        try:
1605817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng            return inner_text_search.group(1)
1615817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng        except AttributeError:
1625817c231041fd60368e31ca80f18a09b0cc1d289Clifford Cheng            return None
163