예제 #1
0
def test_locator_find_elements():
    selenium = Mock(spec=['find_elements'])
    locator = Locator(xpath='//h1')

    locator.find_elements(selenium)

    selenium.find_elements.assert_called_once_with(By.XPATH, '//h1')
예제 #2
0
def test_locator_protocol_and_dict_kwargs():
    class Class(object):
        def __init__(self, loc):
            self.loc = loc

        def __locator__(self):
            return self.loc

    assert Locator(Class('#foo')) == (By.CSS_SELECTOR, '#foo')
    assert Locator(Class({'xpath': '//h1'})) == (By.XPATH, '//h1')
예제 #3
0
파일: utils.py 프로젝트: quipucords/camayoc
def delete_source(view, source_name):
    """Delete a source through the UI."""
    clear_toasts(view=view)
    dash = DashboardView(view)
    dash.nav.select("Sources")
    wait_for_animation()
    view.wait_for_element(locator=Locator(xpath=(delete_xpath(source_name))))
    GenericLocatorWidget(
        view, locator=Locator(xpath=delete_xpath(source_name))).click()
    # mitigate database lock issue quipucords/quipucords/issues/1275
    wait_for_animation()
    DeleteModalView(view).delete_button.click()
    wait_for_animation()
    clear_toasts(view=view)
    with pytest.raises(NoSuchElementException):
        view.wait_for_element(locator=Locator(xpath=delete_xpath(source_name)),
                              timeout=2)
예제 #4
0
파일: utils.py 프로젝트: quipucords/camayoc
def check_auth_type(credential_name, auth_type):
    """Verify the authentication type of a credential.

    Example types include 'SSH Key' and 'Username and Password'.
    If the Locator cannot find a match, an exception is raised.
    """
    Locator(xpath=(f'//span[text()="{auth_type}" and ancestor::node()[2]'
                   f'//*[text()="{credential_name}"]]'))
예제 #5
0
파일: utils.py 프로젝트: quipucords/camayoc
def set_checkbox(view, name, fill):
    """Fill or clear a checkbox next to a credential."""
    checkbox = Checkbox(view, locator=Locator(xpath=checkbox_xpath(name)))
    try:
        checkbox.fill(fill)
    except WidgetOperationFailed:
        clear_toasts(view=view)
        checkbox.fill(fill)
예제 #6
0
파일: utils.py 프로젝트: quipucords/camayoc
def create_source(view, credential_name, source_type, source_name, addresses):
    """Create a source through the UI."""
    clear_toasts(view=view)
    dash = DashboardView(view)
    dash.nav.select("Sources")
    # Display varies depending on whether or not sources already exist.
    wait_for_animation(1)
    try:
        Button(view, "Add Source").click()
    except NoSuchElementException:
        Button(view, "Add").click()

    # Source creation wizard
    modal = SourceModalView(view, locator=Locator(css=".modal-content"))
    radio_label = SOURCE_TYPE_RADIO_LABELS[source_type]

    # Wait for radio button to become responsive before clicking a source type.
    wait_for_animation()
    GenericLocatorWidget(
        modal, locator=Locator(xpath=radio_xpath(radio_label))).click()
    wait_for_animation(1)
    modal.next_button.click()

    # Fill in required source information.
    fill(modal, field_xpath("Name"), source_name)
    if source_type == "Network":
        fill(modal, field_xpath("Search Addresses", textarea=True), addresses)
        fill(modal, field_xpath("Port"), "")  # default port of 22
        cred_dropdown = Dropdown(modal, "Select one or more credentials")
        cred_dropdown.item_select(credential_name)
    else:
        fill(modal, field_xpath("IP Address or Hostname"), addresses)
        cred_dropdown = Dropdown(modal, "Select a credential")
        cred_dropdown.item_select(credential_name)
    Button(modal, "Save").click()
    wait_for_animation(2)
    view.wait_for_element(locator=Locator('//button[text()="Close"]'))
    Button(modal, "Close", classes=[Button.PRIMARY]).click()

    wait_for_animation(1)
    # mitigate database lock issue quipucords/quipucords/issues/1275
    clear_toasts(view=view)
    # Verify that the new row source has been created.
    view.wait_for_element(locator=Locator(xpath=row_xpath(source_name)))
    view.element(locator=Locator(xpath=row_xpath(source_name)))
예제 #7
0
파일: utils.py 프로젝트: quipucords/camayoc
def clear_toasts(view, count=20):
    """Attempt to flush any confirmation dialogs that may have appeared.

    Use this function to clear out dialogs (toasts) that may be
    preventing buttons from being clicked properly. Sometimes it might
    need to be used in succession. By default, this tries to flush a maximum
    of 20 toasts, but will quit early if it cannot find more.
    """
    for i in range(count):
        try:
            view.wait_for_element(locator=Locator(css=".close"), timeout=0.6)
            GenericLocatorWidget(view, locator=Locator(css=".close")).click()
        except (
                MoveTargetOutOfBoundsException,
                NoSuchElementException,
                StaleElementReferenceException,
        ):
            break
예제 #8
0
파일: utils.py 프로젝트: quipucords/camayoc
def delete_credential(view, names):
    """Delete a credential through the UI."""
    view.refresh()
    dash = DashboardView(view)
    dash.nav.select("Credentials")
    # Select all the checkboxes next to the credentials to be deleted.
    for name in names:
        set_checkbox(view, name, True)
    Button(view, "Delete").click()
    DeleteModalView(
        view, locator=Locator(css=".modal-content")).delete_button.click()
    # Wait for the deletion animations to complete,
    # and verify that the rows are gone.
    wait_for_animation(1)
    for name in names:
        with pytest.raises(NoSuchElementException):
            view.wait_for_element(locator=Locator(xpath=row_xpath(name)),
                                  timeout=1)
예제 #9
0
    def __new__(cls, name, bases, attrs):
        new_attrs = {}
        desc_name_mapping = {}
        included_widgets = []
        for base in bases:
            for key, value in six.iteritems(
                    getattr(base, '_desc_name_mapping', {})):
                desc_name_mapping[key] = value
            for widget_includer in getattr(base, '_included_widgets', ()):
                included_widgets.append(widget_includer)
                for widget_name in widget_includer.widget_class.cls_widget_names(
                ):
                    new_attrs[widget_name] = IncludedWidget(
                        widget_includer._seq_id, widget_name,
                        widget_includer.use_parent)

        for key, value in six.iteritems(attrs):
            if inspect.isclass(value) and issubclass(value, View):
                new_attrs[key] = WidgetDescriptor(value)
                desc_name_mapping[new_attrs[key]] = key
            elif isinstance(value, WidgetIncluder):
                included_widgets.append(value)
                # Now generate accessors for each included widget
                for widget_name in value.widget_class.cls_widget_names():
                    new_attrs[widget_name] = IncludedWidget(
                        value._seq_id, widget_name, value.use_parent)
            elif isinstance(value, Widgetable):
                new_attrs[key] = value
                desc_name_mapping[value] = key
                for widget in value.child_items:
                    if not isinstance(widget, (Widgetable, Widget)):
                        continue
                    desc_name_mapping[widget] = key
            elif key == 'fill':
                # handle fill() specifics
                new_attrs[key] = logged(log_args=True, log_result=True)(
                    wrap_fill_method(value))
            elif key == 'read':
                # handle read() specifics
                new_attrs[key] = logged(log_result=True)(value)
            elif isinstance(value, types.FunctionType):
                # VP resolution wrapper, allows to resolve VersionPicks in all widget methods
                new_attrs[key] = resolve_verpicks_in_method(value)
            else:
                # Do nothing
                new_attrs[key] = value
        if 'ROOT' in new_attrs and '__locator__' not in new_attrs:
            # For handling the root locator of the View
            root = new_attrs['ROOT']
            if isinstance(root, ParametrizedLocator):
                new_attrs['__locator__'] = _gen_locator_root()
            else:
                new_attrs['__locator__'] = _gen_locator_meth(Locator(root))
        new_attrs['_included_widgets'] = tuple(
            sorted(included_widgets, key=lambda w: w._seq_id))
        new_attrs['_desc_name_mapping'] = desc_name_mapping
        return super(WidgetMetaclass, cls).__new__(cls, name, bases, new_attrs)
예제 #10
0
파일: utils.py 프로젝트: quipucords/camayoc
def create_credential(view, options):
    """Create a credential through the UI."""
    clear_toasts(view=view)
    dash = DashboardView(view)
    dash.nav.select("Credentials")
    # Display differs depending on whether or not credentials already exist.
    try:
        add_credential_dropdown = Dropdown(view, "Add Credential")
        add_credential_dropdown.item_select(options["source_type"] +
                                            " Credential")
    except NoSuchElementException:
        add_credential_dropdown = Dropdown(view, "Add")
        add_credential_dropdown.item_select(options["source_type"] +
                                            " Credential")
    modal = CredentialModalView(view, locator=Locator(css=".modal-content"))

    # Workaround, should be `assert modal.save_button.disabled`
    # https://github.com/RedHatQE/widgetastic.patternfly/pull/66
    # https://github.com/quipucords/camayoc/issues/279
    assert modal.save_button.browser.get_attribute("disabled",
                                                   modal.save_button)
    fill_credential_info(view, options)

    assert not modal.save_button.browser.get_attribute("disabled",
                                                       modal.save_button)

    # Hack to deal with the fact that the GET refresh isn't
    # implemented when the save button is clicked.
    # https://github.com/quipucords/quipucords/issues/1399
    # https://github.com/quipucords/camayoc/issues/280
    wait_for_animation()
    modal.save_button.click()
    wait_for_animation()
    view.refresh()
    dash.nav.select("Credentials")
    # Assert the row with the credential name exists.
    view.wait_for_element(locator=Locator(xpath=row_xpath(options["name"])),
                          delay=0.5,
                          timeout=10)
    assert isinstance(
        view.element(locator=Locator(xpath=row_xpath(options["name"]))),
        WebElement)
예제 #11
0
def test_simple_css():
    assert Locator('foo#bar.baz.bat') == (By.CSS_SELECTOR, 'foo#bar.baz.bat')
    assert Locator('#bar.baz.bat') == (By.CSS_SELECTOR, '#bar.baz.bat')
    assert Locator('#bar-bar.baz.bat') == (By.CSS_SELECTOR, '#bar-bar.baz.bat')
    assert Locator('#bar') == (By.CSS_SELECTOR, '#bar')
    assert Locator('.bat') == (By.CSS_SELECTOR, '.bat')
    assert Locator('.99-luftballons') == (By.CSS_SELECTOR, '.99-luftballons')
예제 #12
0
 def _process_locator(locator):
     """Processes the locator so the :py:meth:`elements` gets exactly what it needs."""
     if isinstance(locator, WebElement):
         return locator
     try:
         return Locator(locator)
     except TypeError:
         if hasattr(locator, '__locator__'):
             # Deal with the case when __locator__ returns a webelement.
             loc = locator.__locator__()
             if isinstance(loc, WebElement):
                 return loc
         raise LocatorNotImplemented(
             'You have to implement __locator__ on {!r}'.format(type(locator)))
예제 #13
0
 def _process_locator(locator: LocatorAlias) -> Union[WebElement, Locator]:
     """Processes the locator so the :py:meth:`elements` gets exactly what it needs."""
     if isinstance(locator, WebElement):
         return locator
     if hasattr(locator, "__element__"):
         # https://github.com/python/mypy/issues/1424
         return cast("Widget", locator).__element__()
     try:
         return Locator(locator)
     except TypeError:
         if hasattr(locator, "__locator__"):
             # Deal with the case when __locator__ returns a webelement.
             loc = cast(LocatorProtocol, locator).__locator__()
             if isinstance(loc, WebElement):
                 return loc
         raise LocatorNotImplemented(
             f"You have to implement __locator__ on {type(locator)!r}"
         ) from None
예제 #14
0
파일: utils.py 프로젝트: quipucords/camayoc
def edit_credential(view, original_name, options):
    """Edit a credential through the UI and verify it was edited.

    :param view: The view context (should be the browser view)
    :param original_name: The original name of the credential.
    :param options: The options to be edited within the credential.
    """
    view.refresh()
    dash = DashboardView(view)
    dash.nav.select("Credentials")
    view.wait_for_element(locator=Locator(xpath=(edit_xpath(original_name))))
    GenericLocatorWidget(
        view, locator=Locator(xpath=edit_xpath(original_name))).click()
    modal = CredentialModalView(view, locator=Locator(css=".modal-content"))
    wait_for_animation(1)
    fill_credential_info(view, options)
    # Hack to deal with the fact that the GET refresh isn't
    # implemented when the save button is clicked.
    # https://github.com/quipucords/quipucords/issues/1399
    # https://github.com/quipucords/camayoc/issues/280
    wait_for_animation()
    modal.save_button.click()
    wait_for_animation()
    view.refresh()
    dash.nav.select("Credentials")

    # Assert the row with the credential name exists.
    # If the name was updated, use the new name.
    current_name = original_name
    if "name" in options:
        current_name = options["name"]
    view.wait_for_element(locator=Locator(xpath=row_xpath(current_name)),
                          delay=0.5,
                          timeout=10)
    GenericLocatorWidget(
        view, locator=Locator(xpath=edit_xpath(current_name))).click()
    modal = CredentialModalView(view, locator=Locator(css=".modal-content"))

    # Assert that the changed variables were in fact changed.
    # Passwords are skipped because they aren't accessible.
    for option, data in options.items():
        if ((option == "password") or (option == "become_pass")
                or (option == "source_type")):
            continue
        browser_data = get_field_value(view, CREDENTIAL_FIELD_LABELS[option])
        if option == "sshkeyfile":
            # tmp files are resolved with alias prefixes in some cases.
            # the characters afer the final '/' remain consistent.
            assert browser_data.rpartition("/")[2] == data.rpartition("/")[2]
        else:
            assert browser_data == data
예제 #15
0
 def __get__(self, o, t=None):
     result = super().__get__(o, t)
     if isinstance(result, ParametrizedString):
         return result
     else:
         return Locator(result)
예제 #16
0
class DashboardView(View):
    """Dashboard view."""

    user_dropdown = NavDropdown(locator=Locator(css="li.dropdown:nth-child(2)"))
    logout = Button("Log out")
    nav = VerticalNavigation(locator=(Locator(css=".list-group")))
예제 #17
0
def test_bad_param():
    with pytest.raises(TypeError):
        Locator(1)
예제 #18
0
def test_many_params():
    with pytest.raises(TypeError):
        Locator('foo', 'bar', 'baz')
예제 #19
0
def test_bad_strategy_tuple():
    with pytest.raises(ValueError):
        Locator('foo', 'bar')
예제 #20
0
def test_bad_strategy_kwarg():
    with pytest.raises(ValueError):
        Locator(by='foo', locator='bar')
예제 #21
0
def test_bad_kwarg():
    with pytest.raises(ValueError):
        Locator(foo='bar')
예제 #22
0
def test_kwargs_no_by():
    with pytest.raises(ValueError):
        Locator(locator='bar')
예제 #23
0
def test_kwargs_no_locator():
    with pytest.raises(ValueError):
        Locator(by='xpath')
예제 #24
0
def test_implicit_xpath():
    assert Locator('//h1') == (By.XPATH, '//h1')
예제 #25
0
def test_no_params():
    with pytest.raises(TypeError):
        Locator()
예제 #26
0
def test_selenium_like():
    assert Locator(By.XPATH, '//h1') == (By.XPATH, '//h1')
예제 #27
0
파일: utils.py 프로젝트: quipucords/camayoc
def fill(view, xpath_locator, text):
    """Fill in a textbox using a xpath locator."""
    TextInput(view, locator=Locator(xpath=xpath_locator)).fill(text)
예제 #28
0
def test_nested_locator():
    loc = Locator(By.XPATH, '//h1')
    loc2 = Locator(loc)
    assert loc2 == (By.XPATH, '//h1')
    assert loc2 is loc