Skip to content

Commit

Permalink
Add support for CVE modal and PF4 version of LCE Selector (SatelliteQ…
Browse files Browse the repository at this point in the history
…E#1514) (SatelliteQE#1524)

(cherry picked from commit a8368e7)

Co-authored-by: Samuel Bible <[email protected]>
  • Loading branch information
Satellite-QE and sambible authored Sep 4, 2024
1 parent 297fda9 commit 1d5288c
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 3 deletions.
19 changes: 19 additions & 0 deletions airgun/entities/all_hosts.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
BuildManagementDialog,
BulkHostDeleteDialog,
HostDeleteDialog,
ManageCVEModal,
ManagePackagesModal,
)
from airgun.views.job_invocation import JobInvocationCreateView
Expand Down Expand Up @@ -82,6 +83,24 @@ def build_management(self, reboot=False, rebuild=False):
self.browser.wait_for_element(view.alert_message, exception=False)
return view.alert_message.read()

def manage_cve(self, lce=None, cv=None):
"""Bulk reassign Content View Environments through the All Hosts page
args:
lce (str): Lifecycle Environment to swap the hosts to.
cv (str): CV within that LCE to assign the hosts to.
"""
view = self.navigate_to(self, 'All')
self.browser.plugin.ensure_page_safe(timeout='5s')
view.wait_displayed()
view.select_all.fill(True)
view.bulk_actions_kebab.click()
self.browser.move_to_element(view.bulk_actions_menu.item_element('Manage content'))
view.bulk_actions.item_select('Content view environments')
view = ManageCVEModal(self.browser)
view.lce_selector.fill({lce: True})
view.content_source_select.item_select(cv)
view.save_btn.click()

def manage_table_columns(self, values: dict):
"""
Select which columns should be displayed in the hosts table.
Expand Down
44 changes: 42 additions & 2 deletions airgun/views/all_hosts.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
from widgetastic.widget import Checkbox, Text, View
from widgetastic_patternfly4 import Button, Dropdown, Menu, Modal, Pagination, Radio
from widgetastic.widget import Checkbox, ParametrizedView, Text, View
from widgetastic_patternfly4 import (
Button,
Dropdown,
Menu,
Modal,
Pagination,
Radio,
Select,
)
from widgetastic_patternfly4.ouia import (
Alert as OUIAAlert,
PatternflyTable,
)

from airgun.views.common import (
BaseLoggedInView,
PF4LCESelectorGroup,
SearchableViewMixinPF4,
WizardStepView,
)
Expand All @@ -20,6 +29,19 @@ class AllHostsMenu(Menu):
ROOT = f"{BUTTON_LOCATOR}/.."


class AllHostsSelect(Select):
BUTTON_LOCATOR = ".//button[@aria-label='Options menu']"
ITEMS_LOCATOR = ".//ul[contains(@class, 'pf-c-select__menu')]/li"
ITEM_LOCATOR = (
"//*[contains(@class, 'pf-c-select__menu-item') and .//*[contains(normalize-space(.), {})]]"
)
SELECTED_ITEM_LOCATOR = ".//span[contains(@class, 'ins-c-conditional-filter')]"
TEXT_LOCATOR = ".//div[contains(@class, 'pf-c-select') and child::button]"
DEFAULT_LOCATOR = (
'.//div[contains(@class, "pf-c-select") and @data-ouia-component-id="select-content-view"]'
)


class AllHostsTableView(BaseLoggedInView, SearchableViewMixinPF4):
title = Text("//h1[normalize-space(.)='Hosts']")
select_all = Checkbox(
Expand Down Expand Up @@ -130,6 +152,24 @@ def fill(self, values):
self.checkbox_group.fill(values)


class ManageCVEModal(Modal):
"""
This class represents the Manage Content View Environments modal that is used to update the CVE of hosts.
"""

ROOT = './/div[@data-ouia-component-id="bulk-change-host-cv-modal"]'

title = Text("//span[normalize-space(.)='Edit content view environments']")
save_btn = Button(locator='//button[normalize-space(.)="Save"]')
cancel_btn = Button(locator='//button[normalize-space(.)="Cancel"]')
content_source_select = AllHostsSelect()
lce_selector = ParametrizedView.nested(PF4LCESelectorGroup)

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


class ManagePackagesModal(Modal):
"""
This class represents the Manage Packages modal that is used to install or update packages on hosts.
Expand Down
14 changes: 14 additions & 0 deletions airgun/views/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
ItemsList,
LCESelector,
Pf4ConfirmationDialog,
PF4LCESelector,
PF4NavSearch,
PF4Search,
ProgressBar,
Expand Down Expand Up @@ -271,6 +272,19 @@ def read(self):
return self.lce.read()


class PF4LCESelectorGroup(LCESelectorGroup):
ROOT = './/div[./div[@class="env-path"]]'

PARAMETERS = ('lce_name',)

LAST_ENV = './/div[@class="env-path"][last()]'
lce = PF4LCESelector(
locator=ParametrizedLocator(
'.//div[@class="env-path" and .//*[contains(normalize-space(.), "{lce_name}")]]'
)
)


class ListRemoveTab(SatSecondaryTab):
"""'List/Remove' tab, part of :class:`AddRemoveResourcesView`."""

Expand Down
29 changes: 28 additions & 1 deletion airgun/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
Kebab,
VerticalNavigation,
)
from widgetastic_patternfly4 import Button as PF4Button, Pagination as PF4Pagination
from widgetastic_patternfly4 import (
Button as PF4Button,
Pagination as PF4Pagination,
)
from widgetastic_patternfly4.ouia import (
BaseSelect,
Button as OUIAButton,
Expand Down Expand Up @@ -1483,6 +1486,30 @@ def fill(self, value):
return self.select(checkbox_locator, checkbox_value)


class PF4LCESelector(LCESelector):
"""Group of checkboxes that goes in a line one after another. Usually used
to specify lifecycle environment, updated for PF4 pages
"""

LABELS = './/label[contains(@class, "pf-c-radio__label")]'
CHECKBOX = (
'.//input[contains(@class, "pf-c-radio__input") and ../label[.//*[contains(text(), "{}")]]]'
)

def __init__(self, parent, locator=None, logger=None):
"""Allow to specify ``locator`` if needed or use default one otherwise.
Locator is needed when multiple :class:`LCESelector` are present,
typically as a part of :class:`airgun.views.common.LCESelectorGroup`.
"""
if locator is None:
locator = './/div[contains(@class, "env-path")]'
super().__init__(parent, locator, logger=logger)

def checkbox_selected(self, locator):
"""Identify whether specific checkbox is selected or not"""
return self.browser.is_selected(locator)


class LimitInput(Widget):
"""Input for managing limits (e.g. Hosts limit). Consists of 'Unlimited'
checkbox and text input for specifying the limit, which is only visible if
Expand Down

0 comments on commit 1d5288c

Please sign in to comment.