예제 #1
0
    class errata(SatTab):
        lce_filter = Select(
            locator='.//select[@ng-model="selectedErrataOption"]')
        searchbox = Search()
        apply_selected = ActionsDropdown(
            ".//span[contains(@class, 'btn-group')]")
        recalculate = Button('Recalculate')
        table = SatTable('.//table',
                         column_widgets={
                             0: Checkbox(locator="./input[@type='checkbox']"),
                             'Id': Text('./a'),
                         })

        def search(self, query, lce=None):
            """Apply available filters before proceeding with searching and
            automatically set proper search mask if errata id instead of errata
            title was passed.

            :param str query: search query to type into search field. Both
                errata id (RHEA-2012:0055) and errata title (Sea_Erratum) are
                supported.
            :param str optional lce: filter by lifecycle environment
            :return: list of dicts representing table rows
            :rtype: list
            """
            if lce is not None:
                self.lce_filter.fill(lce)

            if re.search(r'\w{4}-\d{4}:\d{4}', query):
                query = 'id = {}'.format(query)
            self.searchbox.search(query)

            return self.table.read()
예제 #2
0
    class repositories(SatTab):
        lce_filter = SatSelect(".//select[@ng-model='environmentFilter']")
        cv_filter = SatSelect(".//select[@ng-model='contentViewFilter']")
        searchbox = Search()
        table = SatTable(locator=".//table",
                         column_widgets={
                             'Name': Text("./a"),
                             'Product': Text("./a"),
                         })

        def search(self, query, lce=None, cv=None):
            """Apply available filters before proceeding with searching.

            :param str query: search query to type into search field.
            :param str optional lce: filter by lifecycle environment name
            :param str optional cv: filter by content view name
            :return: list of dicts representing table rows
            :rtype: list
            """
            if lce:
                self.lce_filter.fill(lce)
            if cv:
                self.cv_filter.fill(cv)
            self.searchbox.search(query)
            return self.table.read()
예제 #3
0
    class AddTab(SatSecondaryTab):
        TAB_NAME = 'Add'
        searchbox = Search()
        add_button = Text('.//div[@data-block="list-actions"]'
                          '//button[contains(@ng-click, "add")]')
        table = Table(locator=".//table")
        columns_exists = Text(
            ".//table//*[contains(name(), 'body')]/tr[1]/td[2]")

        def search(self, value):
            self.searchbox.search(value)
            return self.browser.element(self.parent_view.checkbox_locator %
                                        value)

        def add(self, value):
            checkbox = self.search(value)
            checkbox.click()
            self.add_button.click()

        def fill(self, values):
            if not isinstance(values, list):
                values = list((values, ))
            for value in values:
                self.add(value)

        def read(self):
            if self.columns_exists.is_displayed:
                return self.parent_view.table_labels(self.table)
            return []
예제 #4
0
class SearchableViewMixin(WidgetMixin):
    """Mixin which adds :class:`airgun.widgets.Search` widget and
    :meth:`search` to your view. It's useful for _most_ entities list views
    where searchbox is present.

    Note that you can override expected result locator for the element which is
    returned by :meth:`search` by specifying custom ``search_result_locator``
    string variable in your view class.
    """
    searchbox = Search()
    search_result_locator = "//a[contains(., '%s')]"

    def search(self, query, expected_result=None):
        """Perform search using searchbox on the page and return element text
        if found.

        :param str query: search query to type into search field. E.g. ``foo``
            or ``name = "bar"``.
        :param str optional expected_result: expected resulting entity name.
            Useful when you specify custom search query, not just entity name.
            Defaults to ``query``.
        :return: name of entity (if found) or None
        :rtype: str or None
        """
        self.searchbox.search(query)
        try:
            result = self.browser.element(self.search_result_locator %
                                          (expected_result or query)).text
        except NoSuchElementException:
            result = None
        return result
예제 #5
0
    class content_hosts(SatTab):
        TAB_NAME = 'Content Hosts'
        environment_filter = SatSelect(
            ".//select[@ng-model='environmentFilter']")
        searchbox = Search()
        apply = Text(".//button[@ng-click='goToNextStep()']")
        table = SatTable(
            locator=".//table",
            column_widgets={
                0: Checkbox(locator="./input[@type='checkbox']"),
                'Name': Text("./a"),
            },
        )

        def search(self, query, environment=None):
            """Apply environment filter before proceeding with searching.

            :param str query: search query to type into search field.
            :param str optional environment: filter by environment name
            :return: list of dicts representing table rows
            :rtype: list
            """
            if environment:
                self.environment_filter.fill(environment)
            self.searchbox.search(query)
            return self.table.read()
예제 #6
0
class ApplyErrataView(BaseLoggedInView):
    breadcrumb = BreadCrumb()
    environment_filter = SatSelect(".//select[@ng-model='environmentFilter']")
    searchbox = Search()
    next_button = Text(".//button[@ng-click='goToNextStep()']")
    table = SatTable(locator=".//table",
                     column_widgets={
                         0: Checkbox(locator="./input[@type='checkbox']"),
                         'Name': Text("./a"),
                     })

    def search(self, query, environment=None):
        """Apply environment filter before proceeding with searching.

        :param str query: search query to type into search field.
        :param str optional environment: filter by environment name
        :return: list of dicts representing table rows
        :rtype: list
        """
        if environment:
            self.environment_filter.fill(environment)
        self.searchbox.search(query)
        return self.table.read()

    @property
    def is_displayed(self):
        breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb,
                                                          exception=False)
        return (breadcrumb_loaded and self.breadcrumb.locations[0] == 'Errata'
                and self.breadcrumb.read() == 'Select Content Host(s)')
예제 #7
0
    class ListRemoveTab(SatSecondaryTab):
        TAB_NAME = 'List/Remove'
        searchbox = Search()
        remove_button = Text('.//button[@ng-click="removeSelected()"]')
        table = Table(locator=".//table")
        no_rows = Text(".//table//span[@data-block='no-rows-message' or "
                       "@data-block='no-search-results-message']")

        def search(self, value):
            self.searchbox.search(value)
            return self.browser.element(self.parent_view.checkbox_locator %
                                        value)

        def remove(self, value):
            checkbox = self.search(value)
            checkbox.click()
            self.remove_button.click()

        def fill(self, values):
            if not isinstance(values, list):
                values = list((values, ))
            for value in values:
                self.remove(value)

        def read(self):
            if self.no_rows.is_displayed:
                return []
            return [row.name.text for row in self.table.rows()]
예제 #8
0
    class versions(SatTab):
        searchbox = Search()
        table = SatTable(
            locator='//table',
            column_widgets={
                'Version': Text('.//a'),
                'Status': PublishPromoteProgressBar(),
                'Actions':
                ActionsDropdown('./div[contains(@class, "btn-group")]')
            },
        )

        def search(self, version_name):
            """Searches for content view version.

            Searchbox can't search by version name, only by id, that's why in
            case version name was passed, it's transformed into recognizable
            value before filling, for example::

                'Version 1.0' -> 'version = 1'
            """
            search_phrase = version_name
            if version_name.startswith('V') and '.' in version_name:
                search_phrase = 'version = {}'.format(
                    version_name.split()[1].split('.')[0])
            self.searchbox.search(search_phrase)
            return self.table.read()
예제 #9
0
class SearchableViewMixin(WTMixin):
    """Mixin which adds :class:`airgun.widgets.Search` widget and
    :meth:`search` to your view. It's useful for _most_ entities list views
    where searchbox and results table are present.

    Note that class which uses this mixin should have :attr:`table` attribute.
    """
    searchbox = Search()

    def search(self, query):
        """Perform search using searchbox on the page and return table
        contents.

        :param str query: search query to type into search field. E.g. ``foo``
            or ``name = "bar"``.
        :return: list of dicts representing table rows
        :rtype: list
        """
        self.searchbox.search(query)
        if not hasattr(self, 'table'):
            raise AttributeError(
                'Class {} does not have attribute "table". SearchableViewMixin'
                ' only works with views, which have table for results. Please '
                'define table or use custom search implementation instead'
                .format(self.__class__.__name__)
            )
        return self.table.read()
예제 #10
0
    class AddTab(SatSecondaryTab):
        TAB_NAME = 'Add'
        searchbox = Search()
        add_button = Text(
            './/div[@data-block="list-actions"]'
            '//button[contains(@ng-click, "add")]'
        )

        def search(self, value):
            self.searchbox.search(value)
            return self.browser.element(
                self.parent_view.checkbox_locator % value)

        def add(self, value):
            checkbox = self.search(value)
            checkbox.click()
            self.add_button.click()

        def fill(self, values):
            if not isinstance(values, list):
                values = list((values,))
            for value in values:
                self.add(value)

        def read(self):
            return self.parent_view.table.read()
예제 #11
0
class ListRemoveTab(SatSecondaryTab):
    """'List/Remove' tab, part of :class:`AddRemoveResourcesView`."""
    TAB_NAME = 'List/Remove'
    searchbox = Search()
    remove_button = Text('.//div[@data-block="list-actions"]'
                         '//button[contains(@ng-click, "remove")]')
    table = SatTable(
        locator=".//table",
        column_widgets={0: Checkbox(locator=".//input[@type='checkbox']")})

    def search(self, value):
        """Search for specific associated resource and return the results"""
        self.searchbox.search(value)
        return self.table.read()

    def remove(self, value):
        """Remove specific associated resource"""
        self.search(value)
        next(self.table.rows())[0].widget.fill(True)
        self.remove_button.click()

    def fill(self, values):
        """Remove associated resource(s)."""
        if not isinstance(values, list):
            values = list((values, ))
        for value in values:
            self.remove(value)

    def read(self):
        """Return a list of associated resources"""
        return self.table.read()
예제 #12
0
파일: filter.py 프로젝트: vikask18/airgun
class FiltersView(BaseLoggedInView):
    breadcrumb = BreadCrumb()
    searchbox = Search()
    new = Text("//a[contains(@href, '/filters/new')]")
    table = SatTable(
        ".//table",
        column_widgets={
            'Actions': ActionsDropdown("./div[contains(@class, 'btn-group')]"),
        })

    @property
    def is_displayed(self):
        breadcrumb_loaded = self.browser.wait_for_element(self.breadcrumb,
                                                          exception=False)
        return (breadcrumb_loaded and self.breadcrumb.locations[0] == 'Roles'
                and self.breadcrumb.read().endswith(' filters'))

    def search(self, query):
        value = self.searchbox.read()
        role_id = [int(s) for s in value.split() if s.isdigit()]
        if len(role_id) > 0:
            query = 'role_id = {} and resource = "{}"'.format(
                role_id[0], query)
        self.searchbox.search(query)
        return self.table.read()
예제 #13
0
class AddTab(SatSecondaryTab):
    TAB_NAME = 'Add'
    searchbox = Search()
    add_button = Text('.//div[@data-block="list-actions"]'
                      '//button[contains(@ng-click, "add")]')
    table = SatTable(
        locator=".//table",
        column_widgets={0: Checkbox(locator=".//input[@type='checkbox']")})

    def search(self, value):
        """Search for specific available resource and return the results"""
        self.searchbox.search(value)
        return self.table.read()

    def add(self, value):
        """Associate specific resource"""
        self.search(value)
        next(self.table.rows())[0].widget.fill(True)
        self.add_button.click()

    def fill(self, values):
        """Associate resource(s)"""
        if not isinstance(values, list):
            values = list((values, ))
        for value in values:
            self.add(value)

    def read(self):
        """Return a list of available resources"""
        return self.table.read()
예제 #14
0
class ArchitectureView(BaseLoggedInView):
    title = Text("//h1[text()='Architectures']")
    new = Text("//a[contains(@href, '/architectures/new')]")
    edit = Text("//a[contains(@href, 'edit') and contains(@href, 'arch')]")
    searchbox = Search()

    @property
    def is_displayed(self):
        return self.browser.wait_for_element(self.title,
                                             exception=False) is not None
예제 #15
0
 class affected_repositories(SatSecondaryTab):
     TAB_NAME = 'Affected Repositories'
     filter_toggle = RadioGroup(".//div[@class='col-sm-8']")
     product_filter = Select(locator=".//select[@ng-model='product']")
     searchbox = Search()
     update_repositories = Button('Update Repositories')
     table = SatTable(
         locator='//table',
         column_widgets={0: Checkbox(locator=".//input[@type='checkbox']")},
     )
예제 #16
0
class OperatingSystemView(BaseLoggedInView):
    title = Text("//h1[text()='Operating systems']")
    new = Text("//a[contains(@href, '/operatingsystems/new')]")
    delete = GenericLocatorWidget(
        "//span[contains(@class, 'btn')]/a[@data-method='delete']")
    searchbox = Search()

    @property
    def is_displayed(self):
        return self.browser.wait_for_element(self.title,
                                             exception=False) is not None
예제 #17
0
파일: audit.py 프로젝트: synkd/airgun
class AuditsView(BaseLoggedInView):
    title = Text("//h1[text()='Audits']")
    searchbox = Search()
    entry = AuditEntry()

    @property
    def is_displayed(self):
        return self.browser.wait_for_element(self.title,
                                             exception=False) is not None

    def search(self, query):
        self.searchbox.search(query)
        return self.entry.read()
예제 #18
0
파일: errata.py 프로젝트: vijay8451/airgun
class ErratumView(BaseLoggedInView):
    title = Text("//h1[contains(., 'Errata')]")
    table = SatTable(
        locator='.//table',
        column_widgets={
            0: Checkbox(locator=".//input[@type='checkbox']"),
            'Errata ID': Text("./a"),
        }
    )
    repo_filter = SatSelect(".//select[@ng-model='repository']")
    applicable_filter = Checkbox(
        locator=".//input[@ng-model='showApplicable']")
    installable_filter = Checkbox(
        locator=".//input[@ng-model='showInstallable']")
    apply_errata = Text(
        ".//button[contains(@class, 'btn-primary')]"
        "[@ng-click='goToNextStep()']"
    )
    searchbox = Search()

    def search(self, query, applicable=True, installable=False, repo=None):
        """Apply available filters before proceeding with searching and
        automatically set proper search mask if errata id instead of errata
        title was passed.

        :param str query: search query to type into search field. Both errata
            id (RHEA-2012:0055) and errata title (Sea_Erratum) are supported.
        :param bool applicable: filter by only applicable errata
        :param bool installable: filter by only installable errata
        :param str optional repo: filter by repository name
        :return: list of dicts representing table rows
        :rtype: list
        """
        self.installable_filter.fill(installable)
        self.applicable_filter.fill(applicable)
        if repo is not None:
            self.repo_filter.fill(repo)

        if re.search(r'\w{4}-\d{4}:\d{4}', query):
            query = 'id = {}'.format(query)
        self.searchbox.search(query)

        return self.table.read()

    @property
    def is_displayed(self):
        return self.browser.wait_for_element(
            self.title, exception=False) is not None
예제 #19
0
class EntitySearchView(SatSecondaryTab):
    repo_filter = SatSelect(".//select[@ng-model='repository']")
    searchbox = Search()
    table = Table(".//table")

    def search(self, query, repo=None):
        """Apply available filters before proceeding with searching.

        :param str query: search query to type into search field.
        :param str optional repo: filter by repository name
        :return: list of dicts representing table rows
        :rtype: list
        """
        if repo:
            self.repo_filter.fill(repo)
        self.searchbox.search(query)
        return self.table.read()
예제 #20
0
    class puppet_modules(SatTab):
        TAB_NAME = 'Puppet Modules'

        cv_filter = SatSelect(".//select[@ng-model='contentView']")
        searchbox = Search()
        table = SatTable(locator=".//table")

        def search(self, query, cv=None):
            """Apply available filters before proceeding with searching.

            :param str query: search query to type into search field.
            :param str optional cv: filter by content view name
            :return: list of dicts representing table rows
            :rtype: list
            """
            if cv:
                self.cv_filter.fill(cv)
            self.searchbox.search(query)
            return self.table.read()
예제 #21
0
파일: package.py 프로젝트: vikask18/airgun
class PackagesView(BaseLoggedInView):
    """Main Packages view"""
    title = Text("//h2[contains(., 'Packages')]")
    table = SatTable('.//table', column_widgets={'RPM': Text("./a")})

    repository = Select(locator=".//select[@ng-model='repository']")
    applicable = Checkbox(locator=".//input[@ng-model='showApplicable']")
    upgradable = Checkbox(locator=".//input[@ng-model='showUpgradable']")
    search_box = Search()

    def search(self,
               query,
               repository='All Repositories',
               applicable=False,
               upgradable=False):
        """Perform search using search box on the page and return table
        contents.

        :param str query: search query to type into search field. E.g.
            ``name = "bar"``.
        :param str repository: repository name to select when searching for the
            package.
        :param bool applicable: To show only applicable packages
        :param bool upgradable: To show only upgradable packages
        :return: list of dicts representing table rows
        :rtype: list
        """
        self.repository.fill(repository)
        # set the upgradable first as if enabled, applicable element will be
        # disabled
        self.upgradable.fill(upgradable)
        if not upgradable:
            self.applicable.fill(applicable)
        self.search_box.search(query)
        return self.table.read()

    @property
    def is_displayed(self):
        """The view is displayed when it's title exists"""
        return self.browser.wait_for_element(self.title,
                                             exception=False) is not None
예제 #22
0
파일: common.py 프로젝트: pondrejk/airgun
class SearchableViewMixin(WTMixin):
    """Mixin which adds :class:`airgun.widgets.Search` widget and
    :meth:`airgun.widgets.Search.search` to your view. It's useful for _most_ entities list views
    where searchbox and results table are present.

    Note that class which uses this mixin should have :attr: `table` attribute.
    """

    searchbox = Search()
    welcome_message = Text("//div[@class='blank-slate-pf' or @id='welcome']")

    def is_searchable(self):
        """Verify that search procedure can be executed against specific page.
        That means that we have search field present on the page and that page
        is not a welcome one
        """
        if self.searchbox.search_field.is_displayed and (
                not self.welcome_message.is_displayed):
            return True
        return False

    def search(self, query):
        """Perform search using searchbox on the page and return table
        contents.

        :param str query: search query to type into search field. E.g. ``foo``
            or ``name = "bar"``.
        :return: list of dicts representing table rows
        :rtype: list
        """
        if not hasattr(self.__class__, 'table'):
            raise AttributeError(
                f'Class {self.__class__.__name__} does not have attribute "table". '
                'SearchableViewMixin only works with views, which have table for results. '
                'Please define table or use custom search implementation instead'
            )
        if not self.is_searchable():
            return None
        self.searchbox.search(query)

        return self.table.read()
예제 #23
0
    class packages(SatTab):
        cv_filter = SatSelect(".//select[@ng-model='contentView']")
        repo_filter = SatSelect(".//select[@ng-model='repository']")
        searchbox = Search()
        table = SatTable(locator=".//table")

        def search(self, query, cv=None, repo=None):
            """Apply available filters before proceeding with searching.

            :param str query: search query to type into search field.
            :param str optional cv: filter by content view name
            :param str optional repo: filter by repository name
            :return: list of dicts representing table rows
            :rtype: list
            """
            if cv:
                self.cv_filter.fill(cv)
            if repo:
                self.repo_filter.fill(repo)
            self.searchbox.search(query)
            return self.table.read()
예제 #24
0
파일: product.py 프로젝트: synkd/airgun
class CreateDiscoveredReposView(View):
    """View which represent Discovered Repository section in Repository
    Discovery procedure.
    """

    searchbox = Search()
    table = SatTable(
        locator=".//table",
        column_widgets={0: Checkbox(locator=".//input[@ng-change='itemSelected(urlRow)']")},
    )
    create_action = Text("//button[contains(., 'Create Selected')]")

    def fill(self, values):
        """Select necessary repo/repos to be added to new or existing product"""
        if not isinstance(values, list):
            values = list((values,))
        for value in values:
            self.table.row(discovered_repository__contains=value)[0].fill(True)
            self.create_action.click()

    def read(self):
        return self.table.read()
예제 #25
0
class CloudInventoryListView(BaseLoggedInView):
    """Main RH Cloud Inventory Upload view."""
    title = Text("//h1[@class='inventory_title']")
    searchbox = Search()
    allow_auto_upload = InventoryBootstrapSwitch(
        class_name='auto_upload_switcher')
    obfuscate_host_names = InventoryBootstrapSwitch(
        class_name='host_obfuscation_switcher')

    @View.nested
    class inventory_list(ItemsList):
        item_class = InventoryItem

        @property
        def widget_names(self):
            return [item.description for item in self.items()]

        def read(self):
            return {item.description: item.read() for item in self.items()}

    @property
    def is_displayed(self):
        return self.browser.wait_for_element(self.title,
                                             exception=False) is not None
예제 #26
0
class DashboardView(BaseLoggedInView):
    title = Text("//h1[text()='Overview']")
    manage = ActionsDropdown("//div[@class='btn-group']")
    refresh = AutoRefresh()
    searchbox = Search()

    @property
    def is_displayed(self):
        return self.browser.wait_for_element(self.title,
                                             exception=False) is not None

    def search(self, query):
        """Return whole dashboard view as a result of a search

        :param str query: search query to type into search field.
        :return: all view widgets values
        :rtype: dict
        """
        self.searchbox.search(query)
        return self.read()

    @View.nested
    class DiscoveredHosts(View):
        ROOT = ".//li[@data-name='Discovered Hosts']"
        hosts = Table('.//table')
        hosts_count = Text(".//a[@data-id='aid_discovered_hosts']")

    @View.nested
    class HostConfigurationStatus(View):
        ROOT = ".//li[@data-name='Host Configuration Status for All']"
        status_list = ItemValueList()
        total_count = TotalCount()

    @View.nested
    class TaskStatus(View):
        ROOT = ".//li[@data-name='Task Status']"
        states = SatTable(
            './/table',
            column_widgets={'No. of Tasks': Text('./a')},
        )

        def fill(self, values):
            if 'state' not in values or 'result' not in values:
                raise ValueError(
                    'both state and result values have to be provided')
            self.states.row(
                state=values['state'],
                result=values['result'])['No. of Tasks'].widget.click()

    @View.nested
    class HostConfigurationChart(View):
        ROOT = ".//li[@data-name='Host Configuration Chart for All']"
        chart = PieChart(".//div[@id='host_configuration_chart_all']")

    @View.nested
    class ContentViews(View):
        ROOT = ".//li[@data-name='Content Views']"
        content_views = SatTable('.//table',
                                 column_widgets={'Content View': Text('./a')})

    @View.nested
    class SyncOverview(View):
        ROOT = ".//li[@data-name='Sync Overview']"
        syncs = Table('.//table')

    @View.nested
    class HostSubscription(View):
        ROOT = ".//li[@data-name='Host Subscription Status']"
        subscriptions = SatTable('.//table', column_widgets={0: Text('./a')})

        def fill(self, values):
            if 'type' not in values:
                raise ValueError('You need provide subscription task type')
            self.subscriptions.row(
                (0, 'contains',
                 '{}'.format(values['type'])))[0].widget.click()

    @View.nested
    class SubscriptionStatus(View):
        ROOT = ".//li[@data-name='Subscription Status']"
        subscriptions = SatTable('.//table')

    @View.nested
    class LatestErrata(View):
        ROOT = ".//li[@data-name='Latest Errata']"
        erratas = Table('.//table')

    @View.nested
    class NewHosts(View):
        ROOT = ".//li[@data-name='New Hosts']"
        hosts = Table('.//table')

    @View.nested
    class HostCollections(View):
        ROOT = ".//li[@data-name='Host Collections']"
        collections = SatTable('.//table')

    @View.nested
    class LatestFailedTasks(View):
        ROOT = ".//li[@data-name='Latest Warning/Error Tasks']"
        tasks = SatTable('.//table', column_widgets={'Name': Text('./a')})

        def fill(self, values):
            if 'name' not in values:
                raise ValueError('You need provide name of the task')
            self.tasks.row(name=values['name'])['Name'].widget.click()

    @View.nested
    class VirtWhoConfigStatus(View):
        ROOT = ".//li[@data-name='Virt-who Configs Status']"
        config_status = Table('.//table')
        latest_config = Text(".//div[@class='ca']")