Ejemplo n.º 1
0
def test_get_closest_element_rounding_simulate_py2_rounding():
    '''Chromedriver gives element coordinates with one decimal
       precision like x: 28.5. Selenium rounds these to integer.
       This rounding causes uncertainty when calculating the closest
       element. Also, rounding function was changed in Py3 and
       it now uses banker's rounding where it rounds to even number.

       These two tests simulate real life case where Python 2 worked but
       Python 3 did not. I have modified get_closest_element function
       to handle elements with similar distances as if they are same.
    '''
    locator_element = MagicMock()
    locator_element.location = {'x': 29, 'y': 328}
    locator_element.size = {'width': 337, 'height': 31}
    locator_element.get_attribute.return_value = 'foo'

    cand1 = MagicMock()
    cand1.location = {'x': 370, 'y': 302}
    cand1.size = {'width': 96, 'height': 22}
    cand1.get_attribute.return_value = 'foo'

    cand2 = MagicMock()
    cand2.location = {'x': 370, 'y': 332}
    cand2.size = {'width': 96, 'height': 22}
    cand2.get_attribute.return_value = 'foo'

    cand3 = MagicMock()
    cand3.location = {'x': 370, 'y': 363}
    cand3.size = {'width': 96, 'height': 22}
    cand3.get_attribute.return_value = 'foo'

    assert get_closest_element(locator_element, [cand1, cand2, cand3]) == cand2
    assert get_closest_element(locator_element, [cand1, cand3, cand2]) == cand2
    assert get_closest_element(locator_element, [cand3, cand1, cand2]) == cand2
Ejemplo n.º 2
0
def get_checkbox_by_locator(locator, anchor):
    """Get checkbox element.

    Parameters
    ----------
    locator : str
        Either text that points to the checkbox or direct xpath to the
        checkbox. If using direct XPath then add prefix xpath=.
    anchor : str
        Using if locator is not an XPath.

    Returns
    -------
    WebElement
    """
    if locator.startswith("xpath=") or locator.startswith("//"):
        checkbox_element = element.get_unique_element_by_xpath(locator)
        # TODO: Check that the element is actually a checkbox
    else:  # No prefix given
        text_element = text.get_text_using_anchor(locator, anchor)
        xpath = '//input[@type="checkbox"]|//*[@role="checkbox"]'
        checkbox_elements = element.get_webelements_in_active_area(
            xpath, stay_in_current_frame=True)
        checkbox_element = element.get_closest_element(text_element,
                                                       checkbox_elements)
    return checkbox_element, None
Ejemplo n.º 3
0
def test_get_closest_element_two_candidates():
    locator_element = MagicMock()
    locator_element.location = {'x': 28, 'y': 328}
    locator_element.size = {'width': 337, 'height': 31}
    locator_element.get_attribute.return_value = 'foo'

    cand1 = MagicMock()
    cand1.location = {'x': 370, 'y': 332}
    cand1.size = {'width': 96, 'height': 22}
    cand1.get_attribute.return_value = 'foo'

    cand2 = MagicMock()
    cand2.location = {'x': 370, 'y': 432}
    cand2.size = {'width': 96, 'height': 22}
    cand2.get_attribute.return_value = 'foo'

    assert get_closest_element(locator_element, [cand1, cand2]) == cand1
    assert get_closest_element(locator_element, [cand2, cand1]) == cand1
Ejemplo n.º 4
0
def get_element_using_anchor(elements, anchor, **kwargs):
    """Determine correct element from list of elements using anchor.

    Parameters
    ----------
    elements : :obj:`list` of :obj:`WebElement`
    anchor

    Returns
    -------
    WebElement
    """
    if anchor is None:
        # Element was not unique and anchor was not used.
        raise QWebValueError(
            'Found {} elements. Use anchor to determine which is wanted'.
            format(len(elements)))
    # Select by index unless anchor type is text
    if anchor.isdigit() and kwargs.get("anchor_type",
                                       "auto").lower() != "text":
        anchor = int(anchor) - 1
        if anchor < len(elements):
            return elements[anchor]
        raise QWebInstanceDoesNotExistError(
            'Found {} elements. Given anchor was {}'.format(
                len(elements), anchor + 1))
    if isinstance(anchor, str):  # Get closest element to anchor
        kwargs['stay_in_current_frame'] = True
        anchor_element = None
        if CONFIG['MultipleAnchors']:
            anchor_elements = []
            logger.debug(
                'Multiple anchors enabled, trying to find first exact match')
            try:
                anchor_elements = _get_exact_text_element(anchor, **kwargs)
            except NoSuchFrameException:
                logger.debug('Got no such frame from get exact text')
            if len(anchor_elements) > 0:
                # Using first exact match as anchor
                anchor_element = anchor_elements[0]
            else:
                # No exact matches found, trying to find partial
                anchor_elements = get_text_elements(anchor, **kwargs)
                if len(anchor_elements) > 0:
                    logger.debug(
                        'No exact match found, using first partial match')
                    anchor_element = anchor_elements[0]
        else:
            anchor_element = get_unique_text_element(anchor, **kwargs)
        return element.get_closest_element(anchor_element, elements)
    raise TypeError("Unknown argument type {}".format(type(anchor)))
Ejemplo n.º 5
0
def get_dropdown_element_by_locator(locator, anchor):
    """Find dropdown element.

    Parameters
    ----------
    locator : str
        Text that locates the input field. The input field that is closest
        to the text is selected. Also one can use xpath by adding xpath= prefix
        and then the xpath. Error is raised if the xpath matches to multiple
        elements.
    anchor : str
        Text near the input field's locator element. If the page contains
        many places where the locator is then anchor is used to get the
        one that is closest to it.
    """
    if locator.startswith("xpath=") or locator.startswith("//"):
        dropdown_element = element.get_unique_element_by_xpath(locator)
    else:  # Search using text
        # First we look through all select elements' options, matching locator
        matches = []
        elements = _get_all_dropdown_elements()
        for dd_element in elements:
            options = [x.text for x in Select(dd_element).options]
            if locator in options:
                logger.debug("Found dropdown with options %s" % options)
                matches.append(dd_element)
        if matches:
            correct_element = text.get_element_using_anchor(matches, anchor)
            return correct_element

        # Then we try to find the element using attributes and text
        dropdown_xpath = (
            #  pylint: disable=line-too-long
            '//select[normalize-space(@placeholder)="{0}" or normalize-space(@value)="{0}" or  normalize-space(text())="{0}"]'
            .format(locator))
        dropdown_elements = element.get_webelements_in_active_area(
            dropdown_xpath)
        if len(dropdown_elements) == 1:
            dropdown_element = dropdown_elements[0]
        elif not dropdown_elements:  # Find dropdown element using locator
            locator_element = text.get_text_using_anchor(locator, anchor)
            dropdown_elements = _get_all_dropdown_elements(
                stay_in_current_frame=True)
            dropdown_element = element.get_closest_element(
                locator_element, dropdown_elements)
        else:  # Found many
            logger.debug("found many, using anchor")
            dropdown_element = text.get_element_using_anchor(
                dropdown_elements, anchor)
    return dropdown_element
Ejemplo n.º 6
0
def test_get_closest_element_rounding_simulate_py3_rounding():
    locator_element = MagicMock()
    locator_element.location = {'x': 28, 'y': 328}
    locator_element.size = {'width': 337, 'height': 31}
    locator_element.get_attribute.return_value = 'foo'

    cand1 = MagicMock()
    cand1.location = {'x': 370, 'y': 302}
    cand1.size = {'width': 96, 'height': 22}
    cand1.get_attribute.return_value = 'foo'

    cand2 = MagicMock()
    cand2.location = {'x': 370, 'y': 332}
    cand2.size = {'width': 96, 'height': 22}
    cand2.get_attribute.return_value = 'foo'

    cand3 = MagicMock()
    cand3.location = {'x': 370, 'y': 362}
    cand3.size = {'width': 96, 'height': 22}
    cand3.get_attribute.return_value = 'foo'

    assert get_closest_element(locator_element, [cand1, cand2, cand3]) == cand2
    assert get_closest_element(locator_element, [cand1, cand3, cand2]) == cand2
    assert get_closest_element(locator_element, [cand3, cand1, cand2]) == cand2
Ejemplo n.º 7
0
 def get_table_element(self, locator, anchor):
     if util.xpath_validator(locator):
         table_element = element.get_unique_element_by_xpath(locator)
     else:  # Search using text
         table_xpath = "//*[text()= '{0}']/ancestor::table".format(locator)
         table_elements = element.get_webelements_in_active_area(
             table_xpath)
         if table_elements and len(table_elements) == 1:
             table_element = table_elements[0]
         elif not table_elements:  # Find table element using locator
             locator_element = text.get_text_using_anchor(locator, anchor)
             table_elements = self._get_all_table_elements()
             table_element = element.get_closest_element(
                 locator_element, table_elements)
         else:  # Found many
             table_element = text.get_element_using_anchor(
                 table_elements, anchor)
     if table_element:
         return table_element
     raise QWebElementNotFoundError(
         'Table element not found by locator {}'.format(locator))
Ejemplo n.º 8
0
def get_input_element_by_locator(locator, anchor, **kwargs):
    """Find input element.

    Parameters
    ----------
    locator : str
        Text that locates the input field. The input field that is closest
        to the text is selected. Also one can use xpath by adding xpath= prefix
        and then the xpath. Error is raised if the xpath matches to multiple
        elements.
    anchor : str
        Text near the input field's locator element. If the page contains
        many places where the locator is then anchor is used to get the
        one that is closest to it.
    """
    if locator.startswith("xpath=") or locator.startswith(
            "//") or locator.startswith("(//"):
        if locator.startswith("xpath="):
            xpath = locator.split("=", 1)[1]
        else:
            xpath = locator
        input_element = element.get_unique_element_by_xpath(xpath, **kwargs)
    else:  # Search using text
        input_xpath = CONFIG["MatchingInputElement"].format(locator)
        input_elements = element.get_webelements_in_active_area(
            input_xpath, **kwargs)
        if not input_elements:  # Find input element using locator
            locator_element = text.get_text_using_anchor(
                locator, anchor, **kwargs)
            input_elements = _get_all_input_elements()
            input_element = element.get_closest_element(
                locator_element, input_elements)
        elif len(input_elements) == 1:
            input_element = input_elements[0]  # pylint: disable=unsubscriptable-object
        else:  # Found many
            input_element = text.get_element_using_anchor(
                input_elements, anchor, **kwargs)
    return input_element
Ejemplo n.º 9
0
def test_no_visible_elements():
    with pytest.raises(QWebElementNotFoundError):
        get_closest_element('', [])