Ejemplo n.º 1
0
 def get_table_element_by_css(locator, anchor):
     table_element = javascript.execute_javascript(
         'return document.querySelectorAll(\'table[summary^="{0}"], '
         'table[name^="{0}"], table[title^="{0}"], th[title^="{0}"], '
         'tr[title^="{0}"], td[title^="{0}"]\')'.format(locator))
     if table_element:
         try:
             anchor = int(anchor) - 1
             if table_element[anchor].tag_name == 'table':
                 return table_element[anchor]
             table_element = javascript.execute_javascript(
                 'return arguments[0].closest("table")',
                 table_element[anchor])
             return table_element
         except (ValueError, TypeError):
             raise IndexError(
                 'Element found by it\'s attribute. When using CSS Selectors'  # pylint: disable=W0707
                 ' for finding table, anchor has to be index when anchor is not '
                 'related to separate locator element')
         except StaleElementReferenceException:
             logger.debug('Staling element..Retrying')
             return None
     try:
         locator_element = text.get_text_using_anchor(locator, anchor)
         table_element = javascript.execute_javascript(
             'return arguments[0].closest("table")', locator_element)
     except (ValueError, NoSuchElementException,
             StaleElementReferenceException):
         return None
     if table_element:
         return table_element
     return None
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 get_checkbox_by_css_selector(locator, anchor, index, **kwargs):
    """Get checkbox using css selectors."""
    checkbox_elements = []
    partial_matches = []
    css = '[type="checkbox"], [role="checkbox"]'
    if 'qweb_old' not in kwargs:
        full_matches, partial_matches = element.get_elements_by_css(
            locator, css, **kwargs)
        if full_matches:
            checkbox_elements = element.get_visible_elements_from_elements(
                full_matches, **kwargs)
            if checkbox_elements:
                return checkbox_elements[index], None
    try:
        locator_element = text.get_text_using_anchor(locator, anchor)
        checkbox_elements = list(
            dict.fromkeys(
                element.get_element_from_childnodes(locator_element, css, **
                                                    kwargs) + partial_matches))
        return checkbox_elements[index], locator_element
    except QWebElementNotFoundError:
        logger.trace(
            'Element not found by visible text. Trying with partial match')
        checkbox_elements = partial_matches
    if checkbox_elements:
        logger.debug("Found element {}, index {}".format(
            checkbox_elements, index))
        return checkbox_elements[index], None
    return None, None
Ejemplo n.º 4
0
def get_dropdown_element_by_css_selector(locator, anchor, index, **kwargs):
    """Get Dropdown element using css selectors.
       Parameters
       ----------
       locator : str
           Label text or attribute that points to the dropdown.
           Looking for placeholder and commonly used tooltip-attributes first.
           If locator is label text, finds input element by it's for attribute.
           if for attribute is not available, then finds element by doing some
           DOM traversing.
       anchor : str
           Using if locator is not an XPath.
       index : int
           If multiple elements use index to pick correct one.
       Returns
       -------
       WebElement
   """
    dropdown_elements = []
    partial_matches = []
    css = 'select'
    if 'qweb_old' not in kwargs:
        full_matches, partial_matches = element.get_elements_by_css(
            locator, css, **kwargs)
        if full_matches:
            if index != 0:
                try:
                    return full_matches[index]
                except IndexError as e:
                    raise QWebInstanceDoesNotExistError(
                        f'Found {len(full_matches)} elements. Given index was {index}'
                    ) from e
            correct_element = text.get_element_using_anchor(
                full_matches, anchor)
            return correct_element
    try:
        locator_element = text.get_text_using_anchor(locator, anchor)
        # if this is option, return parent select immediately
        if locator_element.tag_name.lower() == "option":
            return javascript.execute_javascript(
                "return arguments[0].parentNode;", locator_element)
        dropdown_elements = list(
            dict.fromkeys(
                element.get_element_from_childnodes(locator_element, css, **
                                                    kwargs) + partial_matches))
    except QWebElementNotFoundError:
        logger.trace(
            'Element not found by visible text. Trying with partial match')
        dropdown_elements = partial_matches
    if dropdown_elements:
        return dropdown_elements[index]
    return None
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 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.º 7
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.º 8
0
def get_draggable_element(text, index, anchor):
    attribute_match = '[title^="{0}"][draggable="true"],[alt^="{0}"][draggable="true"],' \
                      '[tooltip^="{0}"][draggable="true"],' \
                      '[data-tooltip^="{0}"][draggable="true"],' \
                      '[data-icon^="{0}"][draggable="true"],' \
                      '[aria-label^="{0}"][draggable="true"],' \
                      '[title^="{0}"][class*="draggableCell"]'.format(text)
    web_elements = []
    matches = []
    if text.startswith('xpath=') or text.startswith('//'):
        web_element = element.get_unique_element_by_xpath(text)
        if web_element:
            return web_element
        raise QWebElementNotFoundError('Draggable element not found by locator {}'.format(text))
    try:
        index = int(index) - 1
    except ValueError as e:
        raise QWebValueError('Index needs to be number') from e
    web_elements = javascript.execute_javascript(
        'return document.querySelectorAll(\'{}\')'.format(attribute_match))
    if web_elements:
        return web_elements[index]
    web_elements = javascript.execute_javascript(
        'return document.querySelectorAll(\'[draggable="true"]\')')
    if web_elements:
        matches = _find_matches(web_elements, text)
        if matches:
            return matches[index]
        if text == 'index':
            logger.warn('Text is not matching to any draggable element. Found {} '
                        'draggable elements. Using index..'.format(len(web_elements)))
            return web_elements[index]
        web_elements = get_text_using_anchor(text, anchor)
        if web_elements:
            return web_elements
    raise QWebElementNotFoundError('Draggable element not found by locator {}'.format(text))
Ejemplo n.º 9
0
def drag_drop(locator,
              target_locator,
              index=1,
              anchor="1",
              target_anchor="1",
              timeout=0,
              dragtime='0.5s',
              left=0,
              right=0,
              above=0,
              below=0):
    # pylint: disable=unused-argument
    """Drag and drop element.

    Finds draggable element by it's visible text, tooltip attribute, index
    or xpath.
    Target element is found by it's visible text or xpath.

    Keyword tries to drag element to target element.
    Gets coordinates from WebDriver and uses pyautogui to simulate mouse
    actions based on those coordinates.

    Zoom level needs to be 100% in screen settings so that coordinates
    are matching with actual view. (Preferable resolution 1920x1080)

    Examples
    --------
    .. code-block:: robotframework

        DragDrop       draggable      target
        DragDrop       draggable      //*[@id="some_id"]
        DragDrop       index          Foo       index=3
        DragDrop       draggable      target    dragtime=2s
        DragDrop       draggable      target    right=5   below=2

    Parameters
    ----------
    locator : str
        Visible text, some element attribute(check ClickItem), xpath or
        text index to locate draggable element.
    target_locator : str
        Visible text or xpath to locate target element for draggable.
    index : int
        Index to point out right draggable if there is many or if
        there is no visible text/attribute which can be use to locate
        correct element.
    anchor : str
        In some cases(f.e Angular) element could be draggable even if
        draggable attribute doesn't exists. Then we are using traditional
        text match(check clicktext) to find correct
        element. Anchor can be index or some text near to draggable element.
        (default 1)
    target_anchor
        Text near the target element or index. If the page contains many
        places where the text argument is then anchor is used to get the
        one that is closest to it. (default 1)
    timeout : str | int
        How long we try to find elemenst before failing
    dragtime : str |int
        How long drag should take. Some applications need longer time
    right : int
       Offset how many pixels right of target center we drag
    left : int
       Offset how many pixels left of target center we drag
    above : int
       Offset how many pixels above of target center we drag
    below : int
       Offset how many pixels below of target center we drag
    """
    pyautogui.FAILSAFE = False
    draggable = dragdrop.get_draggable_element(locator, index, anchor)
    if target_locator.startswith('xpath=') or target_locator.startswith('//'):
        target_elem = element.get_unique_element_by_xpath(target_locator)
    else:
        target_elem = internal_text.get_text_using_anchor(
            target_locator, target_anchor)
    x, y = _get_coordinates(draggable)
    logger.debug('draggable x is {} and y is {}'.format(x, y))
    pyautogui.moveTo(x, y)
    x, y = _get_coordinates(target_elem)
    x = x + int(right) - int(left)
    y = y - int(above) + int(below)
    logger.debug('target x is {} and y is {}'.format(x, y))
    dragtime = timestr_to_secs(dragtime)
    pyautogui.dragTo(x, y, dragtime, button='left')
    pyautogui.FAILSAFE = True
Ejemplo n.º 10
0
def get_input_element_by_css_selector(locator,
                                      anchor,
                                      index=0,
                                      enable_check=False,
                                      **kwargs):
    """Get input element using css selectors.
       Parameters
       ----------
       locator : str
           Label text or attribute that points to the input.
           Looking for placeholder and commonly used tooltip-attributes first.
           If locator is label text, finds input element by it's for attribute.
           if for attribute is not available, then finds element by doing some
           DOM traversing.
       anchor : str
           Text near the locator element or index. If placeholder or another
           direct attribute (title, tooltip, value) exists then anchor
           has to be index. Text is aloud when searching by label or some other
           text which is near to input element.
       index: int
            If multiple input elements is nested or in same table cell, index is needed.
       enable_check: bool
            If enable_check is set to true returns first match even if disabled one.
       Returns
       -------
       WebElement
       """
    partial_matches = []
    upload = kwargs.get('upload')
    if upload:
        try:
            index = int(locator) - 1
            kwargs['any_element'] = True
            input_elements = element.get_elements_by_attributes(**kwargs)
            if input_elements:
                return input_elements[index]
        except ValueError:
            logger.debug('locator was text')
    if 'qweb_old' not in kwargs:
        full_matches, partial_matches = element.get_elements_by_css(
            locator, **kwargs)
        if full_matches:
            input_element = element.get_visible_elements_from_elements(
                full_matches, **kwargs)
            if input_element and str(anchor) == '1':
                input_element = input_element[index]
                return input_element
            if input_element:
                input_element = text.get_element_using_anchor(
                    input_element, anchor, **kwargs)
                return input_element
    try:
        locator_element = text.get_text_using_anchor(locator, anchor, **kwargs)
        input_elements = list(
            dict.fromkeys(
                element.get_element_from_childnodes(locator_element, **kwargs)
                + partial_matches))
    except QWebElementNotFoundError:
        logger.trace(
            'Element not found by visible text. Trying with partial match')
        input_elements = partial_matches
    if input_elements:
        visibles = element.get_visible_elements_from_elements(
            input_elements, **kwargs)
        if visibles:
            if element.is_enabled(visibles[index]) or enable_check is True:
                return visibles[index]
    return None