コード例 #1
0
    class fields(ParametrizedView):  # noqa
        PARAMETERS = ("key", )
        input = Input(id=Parameter("key"))
        select = Select(id=Parameter("key"))
        param_input = Input(id=ParametrizedString("param_{key}"))
        dropdown = BootstrapSelect(locator=ParametrizedLocator(
            ".//div[contains(@class, 'bootstrap-select')]/select[@id={key|quote}]/.."
        ))
        param_dropdown = BootstrapSelect(locator=ParametrizedLocator(
            ".//div[contains(@class, 'bootstrap-select')]/select[@id='param_{key}']/.."
        ))

        @property
        def visible_widget(self):
            for widget in (self.input, self.dropdown, self.param_input,
                           self.param_dropdown, self.select):
                try:
                    widget.wait_displayed('2s')
                    return widget
                except TimedOutError:
                    pass
            else:
                raise ItemNotFound("Visible widget is not found")

        def read(self):
            return self.visible_widget.read()

        def fill(self, value):
            return self.visible_widget.fill(value)
コード例 #2
0
    class fields(ParametrizedView):  # noqa
        PARAMETERS = ("key", )
        input = Input(id=Parameter("key"))
        param_input = Input(id=ParametrizedString("param_{key}"))
        dropdown = VersionPick({
            Version.lowest():
            BootstrapSelect(Parameter("key")),
            "5.9":
            DialogFieldDropDownList(
                ParametrizedLocator(".//div[@input-id={key|quote}]"))
        })
        param_dropdown = VersionPick({
            Version.lowest():
            BootstrapSelect(ParametrizedString("param_{key}")),
            "5.9":
            DialogFieldDropDownList(
                ParametrizedLocator(".//div[@input-id='param_{key}']"))
        })

        @property
        def visible_widget(self):
            if self.input.is_displayed:
                return self.input
            elif self.dropdown.is_displayed:
                return self.dropdown
            elif self.param_input.is_displayed:
                return self.param_input
            elif self.param_dropdown.is_displayed:
                return self.param_dropdown

        def read(self):
            return self.visible_widget.read()

        def fill(self, value):
            return self.visible_widget.fill(value)
コード例 #3
0
class CatalogsMultiBoxSelect(MultiBoxSelect):
    available_options = Select(locator=ParametrizedLocator(
        ".//div[contains(text(), {@available_items|quote})]/select"))
    chosen_options = Select(locator=ParametrizedLocator(
        ".//div[contains(text(), {@chosen_items|quote})]/select"))
    move_into_button = Button(title=Parameter("@move_into"))
    move_from_button = Button(title=Parameter("@move_from"))
コード例 #4
0
    class inputs(ParametrizedView):  # noqa
        PARAMETERS = ('name', )
        ROOT = ParametrizedLocator('//tr[./td[2]/input[normalize-space(@value)={name|quote}]]')
        ALL_FIELDS = '//div[@id="inputs_div"]/table//tr/td[2]/input'

        @cached_property
        def row_id(self):
            attr = self.browser.get_attribute(
                'id',
                './/td/input[contains(@id, "fields_name_")]',
                parent=self)
            return int(attr.rsplit('_', 1)[-1])

        name = Input(locator=ParametrizedLocator(
            './/td/input[contains(@id, "fields_name_{@row_id}")]'))
        data_type = Select(locator=ParametrizedLocator(
            './/td/select[contains(@id, "fields_datatype_{@row_id}")]'))
        default_value = Input(locator=ParametrizedLocator(
            './/td/input[contains(@id, "fields_value_{@row_id}")]'))

        @classmethod
        def all(cls, browser):
            results = []
            for e in browser.elements(cls.ALL_FIELDS):
                results.append((browser.get_attribute('value', e), ))
            return results

        def delete(self):
            xpath = './/a/i[contains(@class, "pficon-delete")]'
            self.browser.click(xpath, parent=self)
            try:
                del self.row_id
            except AttributeError:
                pass
コード例 #5
0
class ResourceList(Widget):
    filter = TextInput(locator=ParametrizedLocator(
        "{@parent_locator}//input[@class='ms-filter']"))

    ITEM_FROM = ParametrizedLocator(
        "{@parent_locator}/div[@class='ms-selectable']"
        "//li[not(contains(@style, 'display: none'))]/span[contains(.,'%s')]"
    )
    ITEM_TO = ParametrizedLocator(
        "{@parent_locator}/div[@class='ms-selection']"
        "//li[not(contains(@style, 'display: none'))]/span[contains(.,'%s')]"
    )
    LIST_FROM = ParametrizedLocator(
        "{@parent_locator}/div[@class='ms-selectable']"
        "//li[not(contains(@style, 'display: none'))]"
    )
    LIST_TO = ParametrizedLocator(
        "{@parent_locator}/div[@class='ms-selection']"
        "//li[not(contains(@style, 'display: none'))]"
    )

    def __init__(self, parent, parent_entity, affected_entity, logger=None):
        Widget.__init__(self, parent, logger=logger)
        self.parent_entity = parent_entity.lower()
        self.affected_entity = affected_entity.lower()
        self.parent_locator = (
            "//div[contains(@id, 'ms-{}') and "
            "contains(@id, '{}_ids')]".format(
                self.parent_entity, self.affected_entity)
        )

    def _filter_value(self, value):
        self.filter.fill(value)

    def assign_resource(self, values):
        for value in values:
            self._filter_value(value)
            self.browser.click(
                self.browser.element(self.ITEM_FROM.locator % value))

    def unassign_resource(self, values):
        for value in values:
            self._filter_value(value)
            self.browser.click(
                self.browser.element(self.ITEM_TO.locator % value))

    def fill(self, values):
        if values['operation'] == 'Add':
            self.assign_resource(values['values'])
        if values['operation'] == 'Remove':
            self.unassign_resource(values['values'])

    def read(self):
            return {
                'free': [
                    el.text for el in self.browser.elements(self.LIST_FROM)],
                'assigned': [
                    el.text for el in self.browser.elements(self.LIST_TO)]
            }
コード例 #6
0
class Tab(View):
    """Represents the Patternfly Tab widget.

    Selects itself automatically when any child widget gets accessed, ensuring that the widget is
    visible.

    https://www.patternfly.org/v4/documentation/react/components/tabs
    """

    # The text on the tab. Can be omitted if it is the same as the tab class name capitalized
    TAB_NAME = None

    # Locator of the Tab selector
    TAB_LOCATOR = ParametrizedLocator(
        './/div[contains(@class, "pf-c-tabs")]/ul'
        "/li[button[normalize-space(.)={@tab_name|quote}]]")

    ROOT = ParametrizedLocator(
        ".//section[@aria-labelledby=string("
        "preceding-sibling::div/ul/li/button[normalize-space(.)={@tab_name|quote}]/@id)]"
        "|"
        ".//section[@id=string(../preceding-sibling::div/ul/li"
        "/button[normalize-space(.)={@tab_name|quote}]/@aria-controls)]")

    @property
    def tab_name(self):
        """Returns the tab name as a string."""
        return self.TAB_NAME or type(self).__name__.replace("_",
                                                            " ").capitalize()

    def is_active(self):
        """Returns a boolean detailing of the tab is active."""
        return "pf-m-current" in self.parent_browser.classes(self.TAB_LOCATOR)

    @property
    def is_displayed(self):
        """Returns a boolean detailing of the tab is displayed."""
        return self.parent_browser.is_displayed(self.TAB_LOCATOR)

    def click(self):
        """Clicks the tab."""
        return self.parent_browser.click(self.TAB_LOCATOR)

    def select(self):
        """Selects the tab (checks if active already first)."""
        if not self.is_active():
            self.logger.info("Opening the tab %s", self.tab_name)

            @wait_for_decorator(timeout=3)
            def _click():
                self.click()
                return self.is_active()

    def child_widget_accessed(self, widget):
        # Select the tab
        self.select()

    def __repr__(self):
        return "<Tab {!r}>".format(self.tab_name)
コード例 #7
0
        class select_packages(ParametrizedView):  # noqa
            title = Text(locator=".//h5[normalize-space(.)='Select packages']")
            PARAMETERS = ("pkg", )
            select_all_packages = Text(
                locator=".//input[@class='ant-checkbox-input']")

            packages = Text(
                ParametrizedLocator(
                    ".//div[contains(@class, 'ant-tree-treenode-switcher-close') "
                    "and not(contains(@class, 'ant-tree-treenode-disabled'))]"
                    "/span/span/span[normalize-space(.)={pkg|quote}]"))
            included_packages = Text(
                ParametrizedLocator(
                    ".//li[@class='ant-transfer-list-content-item']"
                    "/span[normalize-space(.)={pkg|quote}]"))
            move_into_button = Button(
                locator=".//span[contains(@class, 'anticon anticon-right')]")
            move_from_button = Button(
                locator=".//span[contains(@class, 'anticon anticon-left')]")

            next_button = Button("Next")
            back_button = Button("Back")
            cancel_button = Button("Cancel")
            fill_strategy = WaitFillViewStrategy("15s")

            @property
            def is_displayed(self):
                return self.title.is_displayed and self.select_all_packages.is_displayed

            def fill_pkg(self):
                """Add packages"""
                self.packages.click()
                self.move_into_button.click()
                was_change = True
                return was_change

            def remove(self):
                """Remove packages"""
                self.included_packages.click()
                self.move_from_button.click()
                was_change = True
                return was_change

            def fill(self, values):
                """
                Args:
                    values: application packages to be selected
                """
                if values.get("pkg"):
                    self.fill_pkg()
                was_change = True
                self.after_fill(was_change)
                return was_change

            def after_fill(self, was_change):
                self.next_button.click()
コード例 #8
0
    class MappingFillView(ParametrizedView):
        PARAMETERS = ("object_type", )

        source = MultiSelectList(ParametrizedLocator("source_{object_type}"))
        target = MultiSelectList(ParametrizedLocator("target_{object_type}"))
        fill_strategy = WaitFillViewStrategy("15s")

        def after_fill(self, was_change):
            if not self.parent.add_mapping.disabled:
                self.parent.add_mapping.click()
コード例 #9
0
    class analysis_row(ParametrizedView):  # noqa
        PARAMETERS = ("row", )

        analysis_number = Text(ParametrizedLocator(".//tr[{row}]/td[1]/a"))
        delete_analysis = Text(
            ParametrizedLocator(
                ".//tr[{row}]//button[@class='pf-c-button pf-m-link']"))

        @property
        def is_displayed(self):
            return self.analysis_number.is_displayed
コード例 #10
0
    class input(ParametrizedView):  # noqa
        PARAMETERS = ("title", )
        field_enable = Text(ParametrizedLocator(
            ".//*[(self::input or self::textarea) and "
            "@title={title|quote}]/../../a[text()='Update']"))
        field_disable = Text(ParametrizedLocator(
            ".//*[(self::input or self::textarea) and "
            "@title={title|quote}]/../../a[text()='Cancel']"))

        def toggle(self):
            if self.field_enable.is_displayed:
                self.field_enable.click()
            elif self.field_disable.is_displayed:
                self.field_disable.click()
コード例 #11
0
    class MappingFillView(ParametrizedView):
        PARAMETERS = ("object_type",)

        source = MultiSelectList(ParametrizedLocator("source_{object_type}"))
        target = MultiSelectList(ParametrizedLocator("target_{object_type}"))
        fill_strategy = WaitFillViewStrategy("15s")

        def after_fill(self, was_change):
            if not self.parent.add_mapping.disabled:
                self.parent.add_mapping.click()

        @property
        def is_displayed(self):
            return (self.source.is_displayed and
                    (len(self.browser.elements(".//div[contains(@class,'spinner')]")) == 0))
コード例 #12
0
class BootstrapSelectByLocator(BootstrapSelect):
    """Modified :py:class:`widgetastic_patternfly.BootstrapSelect` that uses the div locator."""
    ROOT = ParametrizedLocator('{@locator}')

    def __init__(self, parent, locator, can_hide_on_select=False, logger=None):
        BootstrapSelect.__init__(self, parent, locator, can_hide_on_select, logger)
        self.locator = locator
コード例 #13
0
ファイル: rates.py プロジェクト: lcouzens/cfme_tests
    class fields(ParametrizedView):  # noqa
        PARAMETERS = ('name', )
        ROOT = ParametrizedLocator(
            './/tr[./td[contains(normalize-space(.), {name|quote})]]')

        @cached_property
        def row_id(self):
            attr = self.browser.get_attribute(
                'id',
                './td/select[starts-with(@id, "per_time_")]',
                parent=self)
            return int(attr.rsplit('_', 1)[-1])

        @cached_property
        def sub_row_id(self):
            attr = self.browser.get_attribute(
                'id',
                './td/input[starts-with(@id, "fixed_rate_")]',
                parent=self)
            return int(attr.rsplit('_', 1)[-1])

        per_time = Select(id=ParametrizedString('per_time_{@row_id}'))
        per_unit = Select(id=ParametrizedString('per_unit_{@row_id}'))
        start = Input(id=ParametrizedString('start_{@row_id}_{@sub_row_id}'))
        finish = Input(id=ParametrizedString('finish_{@row_id}_{@sub_row_id}'))
        fixed_rate = Input(
            id=ParametrizedString('fixed_rate_{@row_id}_{@sub_row_id}'))
        variable_rate = Input(
            id=ParametrizedString('variable_rate_{@row_id}_{@sub_row_id}'))
        action_add = Button(title='Add a new tier')
        action_delete = Button(title='Remove the tier')
コード例 #14
0
ファイル: instance.py プロジェクト: lcouzens/cfme_tests
    class fields(ParametrizedView):  # noqa
        PARAMETERS = ('name', )
        ROOT = ParametrizedLocator(
            './/tr[./td[1][contains(normalize-space(.), "({name})")]]')
        ALL_FIELDS = './/table//tr/td[1]'

        @cached_property
        def row_id(self):
            attr = self.browser.get_attribute(
                'id',
                './td/input[starts-with(@id, "cls_inst_value_")]',
                parent=self)
            return int(attr.rsplit('_', 1)[-1])

        value = Input(name=ParametrizedString('cls_inst_value_{@row_id}'))
        on_entry = Input(
            name=ParametrizedString('cls_inst_on_entry_{@row_id}'))
        on_exit = Input(name=ParametrizedString('cls_inst_on_exit_{@row_id}'))
        on_error = Input(
            name=ParametrizedString('cls_inst_on_error_{@row_id}'))
        collect = Input(name=ParametrizedString('cls_inst_collect_{@row_id}'))

        @classmethod
        def all(cls, browser):
            results = []
            for e in browser.elements(cls.ALL_FIELDS):
                text = re.sub(r'^\(|\)$', '', browser.text(e))
                results.append((text, ))
            return results
コード例 #15
0
class BootstrapSwitch(Checkbox):
    """ represents checkbox like switch control.
    widgetastic checkbox doesn't work right for this control.
    So, this widget is some kind of enhancement
    .. code-block:: python

        switch = BootstrapSwitch(id="default_tls_verify"')
        switch.fill(True)
        switch.read()
    """
    ROOT = ParametrizedLocator(
        '//div[contains(@class, "bootstrap-switch-container") and '
        '{@input}]')

    def __init__(self, parent, id=None, name=None, logger=None):
        if not (id or name):
            raise ValueError('either id or name should be present')
        elif name is not None:
            id_attr = '@name={}'.format(quote(name))
        else:
            id_attr = '@id={}'.format(quote(id))

        self.input = './/input[{}]'.format(id_attr)

        Checkbox.__init__(self, parent, locator=self.ROOT, logger=logger)

    @property
    def selected(self):
        return self.browser.is_selected(parent=self, locator=self.input)
コード例 #16
0
ファイル: ouia.py プロジェクト: dhlavac/widgetastic.core
class OUIABase:
    """
    Base class for ``OUIA`` support. According to the spec ``OUIA`` compatible components may have
    the following attributes in the root level HTML element:
        * data-ouia-component-type
        * data-ouia-component-id
        * data-ouia-safe
    https://ouia.readthedocs.io/en/latest/README.html#ouia-component
    """

    ROOT = ParametrizedLocator(
        ".//*[@data-ouia-component-type={@component_type}{@component_id}]")

    def __init__(self,
                 component_type,
                 component_id=None,
                 namespace=None,
                 **kwargs):
        component_type = f"{namespace}/{component_type}" if namespace else component_type
        self.component_type = quote(component_type)
        component_id = f" and @data-ouia-component-id={quote(component_id)}" if component_id else ""
        self.component_id = component_id
        self.locator = self.ROOT.locator
        super().__init__(**kwargs)

    @property
    def is_safe(self):
        """
        An attribute called data-ouia-safe, which is True only when the component is in a static
        state, i.e. no animations are occurring. At all other times, this value MUST be False.
        """
        return "true" in self.browser.get_attribute("data-ouia-safe", self)

    def __locator__(self):
        return self.ROOT
コード例 #17
0
class Accordion(View, ClickableMixin):
    """Bootstrap accordions.

    They are like views that contain widgets. If a widget is accessed in the accordion, the
    accordion makes sure that it is open.

    You need to set the ``ACCORDION_NAME`` to correspond with the text in the accordion.
    If the accordion title is just a capitalized version of the accordion class name, you do not
    need to set the ``ACCORDION_NAME``.

    If the accordion is in an exotic location, you also have to change the ``ROOT``.
    https://getbootstrap.com/docs/4.1/components/collapse/#accordion-example

    """
    ACCORDION_NAME = None
    ROOT = ParametrizedLocator(
        './/div[contains(@class, "accordion")]//div[@class="card" and '
        './/div[@class="card-header"]//button[normalize-space(.)={@accordion_name|quote}]]'
    )
    HEADER_LOCATOR = ".//button"

    @property
    def accordion_name(self):
        return self.ACCORDION_NAME or type(self).__name__.capitalize()

    @property
    def is_opened(self):
        attr = self.browser.get_attribute("aria-expanded", self.HEADER_LOCATOR)
        return attr.lower().strip() == "true"

    @property
    def is_closed(self):
        return not self.is_opened

    def click(self):
        """Override Clickable's click."""
        self.browser.click(self.HEADER_LOCATOR)

    def open(self):
        if self.is_closed:
            self.logger.info("opening")
            self.click()
            wait_for(lambda: self.is_opened, delay=0.1, num_sec=3)

    def close(self):
        if self.is_opened:
            self.logger.info("closing")
            self.click()

    def child_widget_accessed(self, widget):
        # Open the Accordion
        self.open()

    def read(self):
        if self.is_closed:
            do_not_read_this_widget()
        return super(Accordion, self).read()

    def __repr__(self):
        return '<Accordion {!r}>'.format(self.accordion_name)
コード例 #18
0
ファイル: topology.py プロジェクト: nachandr/cfme_tests
    class legends(ParametrizedView):  # noqa
        PARAMETERS = ('name', )
        ALL_LEGENDS = './/kubernetes-topology-icon//label'
        el = Text(
            ParametrizedLocator(
                './/kubernetes-topology-icon//label[normalize-space(.)={name|quote}]'
            ))

        @property
        def is_enabled(self):
            el = self.browser.element(
                './ancestor::kubernetes-topology-icon[1]', self.el)
            return 'active' in self.browser.get_attribute('class', el)

        def enable(self):
            if not self.is_enabled:
                self.el.click()

        def disable(self):
            if self.is_enabled:
                self.el.click()

        @property
        def name(self):
            return self.el.text

        @classmethod
        def all(cls, browser):
            return [(browser.text(e), )
                    for e in browser.elements(cls.ALL_LEGENDS)]
コード例 #19
0
class Tab(View, ClickableMixin):
    """Represents the Tab widget.

    Selects itself automatically when any child widget gets accessed, ensuring that the widget is
    visible.
    """
    TAB_NAME = None
    INDIRECT = True
    ROOT = ParametrizedLocator(
        './/ul[contains(@class, "nav-tabs")]/li[normalize-space(.)={@tab_name|quote}]')

    @property
    def tab_name(self):
        return self.TAB_NAME or type(self).__name__.capitalize()

    def is_active(self):
        return 'active' in self.browser.classes(self)

    def is_disabled(self):
        return 'disabled' in self.browser.classes(self)

    def select(self):
        if not self.is_active():
            if self.is_disabled():
                raise ValueError(
                    'The tab {} you are trying to select is disabled'.format(self.tab_name))
            self.logger.info('opened the tab %s', self.tab_name)
            self.click()

    def child_widget_accessed(self, widget):
        # Select the tab
        self.select()

    def __repr__(self):
        return '<Tab {!r}>'.format(self.tab_name)
コード例 #20
0
class TabsView(View):
    ROOT = ParametrizedLocator(".//ul[@id={@id|quote}]/..")
    tabs_names = ["home", "profile", "disabled", "dropdown"]

    def __init__(self, parent, id, logger=None):
        super(TabsView, self).__init__(parent, logger=logger)
        self.id = id

    @View.nested
    class home(Tab):
        pass

    @View.nested
    class profile(Tab):
        PROFILE = ParametrizedLocator("//div[@id=concat({@parent/id|quote}, '-profile')]")
        content = Text(PROFILE)

    @View.nested
    class disabled(Tab):
        pass

    @View.nested
    class dropdown(TabWithDropdown):
        SUB_ITEM = "Action"
        pass
コード例 #21
0
class Alert(Widget):
    """Represents alert block.

    https://www.patternfly.org/v4/documentation/react/components/alert
    """

    ROOT = ParametrizedLocator("{@locator}")
    TITLE = './/h4[@class="pf-c-alert__title"]'
    DESCRIPTION = './/div[@class="pf-c-alert__description"]'
    ACTION = './/div[@class="pf-c-alert__action"]/*'
    TYPE_MAPPING = {
        "pf-m-warning": "warning",
        "pf-m-success": "success",
        "pf-m-danger": "error",
        "pf-m-info": "info",
    }

    def __init__(self, parent, locator, logger=None):
        super(Alert, self).__init__(parent, logger=logger)
        self.locator = locator

    def read(self):
        return self.body

    @property
    def _raw_title_el(self):
        return self.browser.element(self.TITLE)

    @property
    def title(self):
        trim_text = self.browser.text(
            self.browser.element("./span", parent=self._raw_title_el))
        return self.browser.text(self._raw_title_el)[len(trim_text):].strip()

    @property
    def body(self):
        el = self.browser.element(self.DESCRIPTION)
        return self.browser.text(el)

    def click_action(self):
        el = self.browser.element(self.ACTION)
        self.browser.click(el)

    @property
    def type(self):
        for class_ in self.browser.classes(self):
            if class_ in self.TYPE_MAPPING:
                return self.TYPE_MAPPING[class_]
        else:
            raise ValueError("Could not find a proper alert type."
                             " Available classes: {!r} Alert has: {!r}".format(
                                 self.TYPE_MAPPING,
                                 self.browser.classes(self)))

    def assert_no_error(self):
        if self.type == "error":
            raise AssertionError("assert_no_error: {}".format(self.body))

    def __repr__(self):
        return "{}({!r})".format(type(self).__name__, self.locator)
コード例 #22
0
    class fields(ParametrizedView):  # noqa
        PARAMETERS = ("key", )
        input = Input(id=Parameter("key"))
        select = Select(id=Parameter("key"))
        param_input = Input(id=ParametrizedString("param_{key}"))
        dropdown = VersionPick({
            Version.lowest():
            BootstrapSelect(Parameter("key")),
            "5.9":
            BootstrapSelect(locator=ParametrizedLocator(
                './/div[contains(@class, "bootstrap-select")]/select[@id={key|quote}]/..'
            ))
        })
        param_dropdown = VersionPick({
            Version.lowest():
            BootstrapSelect(ParametrizedString("param_{key}")),
            "5.9":
            BootstrapSelect(locator=ParametrizedLocator(
                ".//div[contains(@class, 'bootstrap-select')]/select[@id='param_{key}']/.."
            ))
        })

        @property
        def visible_widget(self):
            if self.browser.wait_for_element(self.input.locator,
                                             exception=False):
                return self.input
            elif self.browser.wait_for_element(self.dropdown.locator,
                                               exception=False):
                return self.dropdown
            elif self.browser.wait_for_element(self.param_input.locator,
                                               exception=False):
                return self.param_input
            elif self.browser.wait_for_element(self.param_dropdown.locator,
                                               exception=False):
                return self.param_dropdown
            elif self.browser.wait_for_element(self.select.locator,
                                               exception=False):
                return self.select
            else:
                raise ItemNotFound("Visible widget is not found")

        def read(self):
            return self.visible_widget.read()

        def fill(self, value):
            return self.visible_widget.fill(value)
コード例 #23
0
        class fields(ParametrizedView):  # noqa
            PARAMETERS = ('name', )
            # Points to the <tr>
            ROOT = ParametrizedLocator(
                './/input[starts-with(@id, "fields_name_") and @value={name|quote}]/../..'
            )
            ALL_FIELDS = './/input[starts-with(@name, "fields_name_")]'

            @cached_property
            def row_id(self):
                attr = self.browser.get_attribute(
                    'id',
                    './td/input[starts-with(@id, "fields_name_")',
                    parent=self)
                return int(attr.rsplit('_', 1)[-1])

            name = Input(name=ParametrizedString('fields_name_{@row_id}'))
            type = BootstrapSelect(
                ParametrizedString('fields_aetype_{@row_id}'))
            data_type = BootstrapSelect(
                ParametrizedString('fields_datatype_{@row_id}'))
            default_value = Input(
                name=ParametrizedString('fields_default_value_{@row_id}'))
            display_name = Input(
                name=ParametrizedString('fields_display_name_{@row_id}'))
            description = Input(
                name=ParametrizedString('fields_description_{@row_id}'))
            substitute = Checkbox(
                name=ParametrizedString('fields_substitute_{@row_id}'))
            collect = Input(
                name=ParametrizedString('fields_collect_{@row_id}'))
            message = Input(
                name=ParametrizedString('fields_message_{@row_id}'))
            on_entry = Input(
                name=ParametrizedString('fields_on_entry_{@row_id}'))
            on_exit = Input(
                name=ParametrizedString('fields_on_exit_{@row_id}'))
            on_error = Input(
                name=ParametrizedString('fields_on_error_{@row_id}'))
            max_retries = Input(
                name=ParametrizedString('fields_max_retries_{@row_id}'))
            max_time = Input(
                name=ParametrizedString('fields_max_time_{@row_id}'))

            def delete(self):
                self.browser.click(
                    './/img[@alt="Click to delete this field from schema"]',
                    parent=self)
                try:
                    del self.row_id
                except AttributeError:
                    pass

            @classmethod
            def all(cls, browser):
                result = []
                for e in browser.elements(cls.ALL_FIELDS):
                    result.append((browser.get_attribute('value', e), ))
                return result
コード例 #24
0
class Button(BaseButton, Widget, ClickableMixin):
    """A Patternfly button

    You can match by text, partial text or by attributes, you can also add the patternfly classes
    into the matching.

    .. code-block:: python

        Button("Text of button (unless it is an input ...)")
        Button("contains", "Text of button (unless it is an input ...)")
        Button(title="Show xyz")  # And such
        Button("Add", classes=[Button.PRIMARY])
        Button(locator=".//xpath")
        assert button.active
        assert not button.disabled
    """

    ROOT = ParametrizedLocator("{@locator}")

    def _generate_locator(self, *text, **kwargs):
        classes = kwargs.pop("classes", [])
        if text:
            if kwargs:  # classes should have been the only kwarg combined with text args
                raise TypeError(
                    "If you pass button text then only pass classes in addition"
                )
            if len(text) == 1:
                locator_conditions = "normalize-space(.)={}".format(
                    quote(text[0]))
            elif len(text) == 2 and text[0].lower() == "contains":
                locator_conditions = "contains(normalize-space(.), {})".format(
                    quote(text[1]))
            else:
                raise TypeError("An illegal combination of args/kwargs")
        else:
            # Join the kwargs, if any
            locator_conditions = " and ".join(
                "@{}={}".format(attr, quote(value))
                for attr, value in kwargs.items())

        if classes:
            if locator_conditions:
                locator_conditions += " and "
            locator_conditions += " and ".join(
                "contains(@class, {})".format(quote(klass))
                for klass in classes)
        if locator_conditions:
            locator_conditions = "and ({})".format(locator_conditions)

        return (".//*[(self::a or self::button or (self::input and "
                "(@type='button' or @type='submit'))) and "
                f"contains(@class, 'pf-c-button') {locator_conditions}]")

    def __init__(self, parent, *text, **kwargs):
        super().__init__(parent, logger=kwargs.pop("logger", None))
        self.args = text
        self.kwargs = kwargs
        self.locator = kwargs.pop("locator",
                                  self._generate_locator(*text, **kwargs))
コード例 #25
0
class Kebab(Dropdown):
    """The so-called "kebab" widget of Patternfly."""

    ROOT = ParametrizedLocator("{@locator}")

    def __init__(self, parent, locator, logger=None):
        Widget.__init__(self, parent, logger=logger)
        self.locator = locator
コード例 #26
0
class Pagination(BasePagination, View):
    ROOT = ParametrizedLocator("{@locator}")

    def __init__(self, parent, locator=None, logger=None):
        super().__init__(parent=parent, logger=logger)
        if not locator:
            locator = self.DEFAULT_LOCATOR
        self.locator = locator
コード例 #27
0
class PlaybookBootstrapSelect(BootstrapSelect):
    """BootstrapSelect widget for Ansible Playbook Method form.

    BootstrapSelect widgets don't have ``data-id`` attribute in this form, so we have to override
    ROOT locator.

    """
    ROOT = ParametrizedLocator('.//select[normalize-space(@name)={@id|quote}]/..')
コード例 #28
0
ファイル: tab.py プロジェクト: mfalesni/widgetastic.bootstrap
class Tab(View):
    """Represents the Tab widget.

    Selects itself automatically when any child widget gets accessed, ensuring that the widget is
    visible.
    https://getbootstrap.com/docs/4.1/components/navs/#tabs

    You can specify your own ``ROOT`` attribute on the class.
    """
    ROOT = None
    #: The text on the tab. If it is the same as the tab class name capitalized, can be omitted
    TAB_NAME = None

    # Locator of the Tab selector
    TAB_ROOT = ParametrizedLocator(
        './/ul[contains(@class, "nav-tabs") or contains(@class, "nav-pills")]'
        '/li[./a[normalize-space(.)={@tab_name|quote}]]')
    NAV_LINK = "./a[contains(@class, 'nav-link')]"

    def __locator__(self):
        return self.ROOT or self.TAB_ROOT

    @property
    def tab_name(self):
        return self.TAB_NAME or type(self).__name__.capitalize()

    @property
    def _tab_el(self):
        return self.parent_browser.element(self.TAB_ROOT)

    @property
    def is_active(self):
        return "active" in self.browser.classes(self.NAV_LINK,
                                                parent=self._tab_el)

    @property
    def is_disabled(self):
        return "disabled" in self.browser.classes(self.NAV_LINK,
                                                  parent=self._tab_el)

    def click(self):
        return self.browser.click(self._tab_el)

    def select(self):
        if not self.is_active:
            if self.is_disabled:
                raise ValueError(
                    "The tab {} you are trying to select is disabled".format(
                        self.tab_name))
            self.logger.info("opened the tab %s", self.tab_name)
            self.click()

    def child_widget_accessed(self, widget):
        # Select the tab
        self.select()

    def __repr__(self):
        return "<Tab {!r}>".format(self.tab_name)
コード例 #29
0
class Card(View):
    ROOT = ParametrizedLocator(
        '//div[contains(@class, "card") and boolean(@data-card) and @data-card={@id|quote}]'
    )
    ALL_CARDS = '//div[contains(@class, "card") and boolean(@data-card)]'
    TITLE = './/h6'
    DESCRIPTION = './/div[contains(@class, "card-body")]/p[1]'

    like_button = GenericLocatorWidget(
        locator='.//button[./*[name()="svg" and @data-icon="thumbs-up"]]')
    delete_button = Button('Delete')

    def __init__(self, parent, id, logger=None):
        View.__init__(self, parent, logger=logger)
        self.id = id

    @property
    def title(self):
        return self.browser.text(self.TITLE)

    @property
    def description(self):
        return self.browser.text(self.DESCRIPTION)

    @property
    def liked(self):
        return bool(int(self.browser.text(self.like_button)))

    def wait_liked(self, liked, timeout='5s'):
        return wait_for(
            lambda: self.like_button.is_displayed and self.liked == liked,
            timeout=timeout,
            delay=1)[0]

    def like(self):
        if not self.liked:
            self.like_button.click()
            return True
        else:
            return False

    def unlike(self):
        if self.liked:
            self.like_button.click()
            return True
        else:
            return False

    def delete(self):
        self.delete_button.click()

    @classmethod
    def all(cls, parent):
        cards = []
        for el in parent.browser.elements(cls.ALL_CARDS):
            card_id = parent.browser.get_attribute('data-card', el)
            cards.append(cls(parent, id=card_id))
        return cards
コード例 #30
0
    class _card(ParametrizedView):
        PARAMETERS = ("card_name", )
        card = Text(
            ParametrizedLocator(
                "//h4[contains(normalize-space(.), {card_name|quote})]"))

        def click_card(self):
            """Clicks the list item with this name."""
            return self.card.click()