Skip to content

Commit

Permalink
removing updated value with default
Browse files Browse the repository at this point in the history
  • Loading branch information
amolpati30 committed Jan 2, 2025
1 parent 74bc1fa commit da56054
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 13 deletions.
22 changes: 22 additions & 0 deletions airgun/entities/host_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def get_details(self, entity_name, widget_names=None):
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.wait_displayed()
self.browser.plugin.ensure_page_safe()
# Run this read twice to navigate to the page and load it before reading
view.read(widget_names=widget_names)
return view.read(widget_names=widget_names)

def get_host_statuses(self, entity_name):
Expand Down Expand Up @@ -783,6 +785,26 @@ def get_host_facts(self, entity_name, fact=None):
host_facts_view.expand_fact_value.click()
return host_facts_view.table.read()

def update_variable_value(self, entity_name, key, value):
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
wait_for(lambda: view.ansible.variables.table.is_displayed, timeout=10)
# Index [5] essentially refers to the button used to edit the value. The same index is then applied to either 'Yes' or 'No' options to update the value
view.ansible.variables.table.row(name=key)[5].widget.click()
view.ansible.variables.table.row(name=key)['Value'].click()
view.ansible.variables.table.row(name=key)['Value'].widget.fill(value)
view.ansible.variables.table1.row(name=key)[5].widget.click()

def del_variable_value(self, entity_name):
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
view.ansible.variables.actions.click()
view.ansible.variables.delete.click()
view.ansible.variables.confirm.click()

def read_variable_value(self, entity_name, key):
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
value = view.ansible.variables.table.row(name=key)['Value'].read()
return value


@navigator.register(NewHostEntity, 'NewDetails')
class ShowNewHostDetails(NavigateStep):
Expand Down
2 changes: 1 addition & 1 deletion airgun/views/ansible_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class MatcherActions(View):
text input field."""

matcher_key = Select(".//select")
matcher_value = TextInput(locator=".//input[@class='matcher_value']")
matcher_value = TextInput(locator=".//div[@class='matcher-group']/input")


class NewAnsibleVariableView(BaseLoggedInView):
Expand Down
23 changes: 15 additions & 8 deletions airgun/views/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
do_not_read_this_widget,
)
from widgetastic_patternfly import BreadCrumb, Button, Tab, TabWithDropdown
from widgetastic_patternfly4.navigation import Navigation
from widgetastic_patternfly4.ouia import Dropdown

from airgun.utils import get_widget_by_name, normalize_dict_values
Expand All @@ -21,13 +22,13 @@
ItemsList,
LCESelector,
Pf4ConfirmationDialog,
PF4NavSearch,
PF4Search,
ProgressBar,
ReadOnlyEntry,
SatFlashMessages,
SatSubscriptionsTable,
SatTable,
SatVerticalNavigation,
Search,
ValidationErrors,
)
Expand All @@ -36,38 +37,44 @@
class BaseLoggedInView(View):
"""Base view for Satellite pages"""

menu = SatVerticalNavigation(
'.//div[@id="vertical-nav" or contains(@class, "nav-pf-vertical")]/ul'
)
menu = Navigation("Global")
menu_search = PF4NavSearch()
taxonomies = ContextSelector()
flash = SatFlashMessages()
validations = ValidationErrors()
dialog = Pf4ConfirmationDialog()
logout = Text("//a[@href='/users/logout']")
current_user = Dropdown('OUIA-Generated-Dropdown-1')
account_menu = Dropdown('OUIA-Generated-Dropdown-1')
current_user = Dropdown('user-info-dropdown')
account_menu = Dropdown('user-info-dropdown')
permission_denied = Text('//*[@id="content"]')

def select_logout(self):
"""logout from satellite"""
self.account_menu.click()
self.logout.click()

def read(self, widget_names=None):
def read(self, widget_names=None, limit=None):
"""Reads the contents of the view and presents them as a dictionary.
:param widget_names: If specified, will read only the widgets names in the list.
:param limit: how many entries to fetch at most
:return: A :py:class:`dict` of ``widget_name: widget_read_value``
where the values are retrieved using the :py:meth:`Widget.read`.
"""
if widget_names is None:
if limit is not None:
raise NotImplementedError("You must specify widgets to be able to specify limit")
return super().read()
if not isinstance(widget_names, list | tuple):
widget_names = [widget_names]
values = {}
for widget_name in widget_names:
values[widget_name] = get_widget_by_name(self, widget_name).read()
widget = get_widget_by_name(self, widget_name)
if hasattr(widget, 'read_limited') and callable(widget.read_limited):
values[widget_name] = widget.read(limit=limit)
else:
values[widget_name] = widget.read()
return normalize_dict_values(values)


Expand Down
18 changes: 14 additions & 4 deletions airgun/views/host_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,20 +508,30 @@ class roles(Tab):
class variables(Tab):
TAB_NAME = 'Variables'
ROOT = './/div[@class="ansible-host-detail"]'

actions = Button(locator='//tbody/tr/td[7]//button')
delete = Button(locator='//button[@role="menuitem"]')
confirm = Button(locator='//button[@data-ouia-component-id="btn-modal-confirm"]')
table = Table(
locator='.//table[contains(@class, "pf-c-table")]',
column_widgets={
'Name': Text('.//a'),
'Ansible role': Text('./span'),
'Type': Text('./span'),
# the next field can also be a form group
'Value': Text('./span'),
'Value': TextInput(locator='//textarea[contains(@class, "pf-c-form")]'),
'Source attribute': Text('./span'),
# The next 2 buttons are hidden by default, but appear in this order
5: Button(locator='.//button[@aria-label="Cancel editing override button"]'),
6: Button(locator='.//button[@aria-label="Submit override button"]'),
6: Button(locator='.//button[@aria-label="Cancel editing override button"]'),
7: Button(locator='.//button[@aria-label="Submit override button"]'),
# Clicking this button hides it, and displays the previous 2
7: Button(locator='.//button[@aria-label="Edit override button"]'),
5: Button(locator='.//button[@aria-label="Edit override button"]'),
},
)
table1 = Table(
locator='.//table[contains(@class, "pf-c-table")]',
column_widgets={
5: Button(locator='.//button[@aria-label="Submit editing override button"]'),
},
)
pagination = PF4Pagination()
Expand Down
67 changes: 67 additions & 0 deletions airgun/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,73 @@ def search(self, value):
self.search_button.click()


class PF4NavSearchMenu(Menu):
"""PF4 vertical navigation dropdown menu with search results."""

@property
def items(self):
"""Return list of :py:class:`WebElement` items in the menu."""
return self.browser.elements(self.ITEMS_LOCATOR)

def read(self):
"""Return all items in the menu as strings."""
return [self.browser.text(el) for el in self.items]


class PF4NavSearch(PF4Search):
"""PF4 vertical navigation menu search"""

ROOT = '//div[@id="navigation-search"]'
search_field = TextInput(locator=(".//input[@aria-label='Search input']"))
search_button = PF4Button(locator=(".//button[@aria-label='Search']"))
clear_button = PF4Button(locator=(".//button[@aria-label='Reset']"))
items = PF4NavSearchMenu("navigation-search-menu")
results_timeout = search_clear_timeout = 2

def _wait_for_results(self, results_widget):
"""Read the search results widget `results_widget` for `self.results_timeout` seconds
and return the values. If timeout is exceeded, empty list is returned.
:return: list[str] if values are returned; empty list otherwise
"""
return (
wait_for(
lambda: results_widget.read(),
timeout=self.results_timeout,
delay=0.5,
handle_exception=NoSuchElementException,
silent_failure=True,
)[0]
or []
)

def _safe_search_clear(self):
"""Clear the search input and return if it is actually cleared."""
if self.browser.text(self.search_field) != '':
self.clear()
return self.browser.text(self.search_field) == ''

def _ensure_search_is_cleared(self):
"""Wait for `search_clear_timeout` seconds that the search input has been really cleared."""
wait_for(
lambda: self._safe_search_clear(),
timeout=self.search_clear_timeout,
delay=0.5,
)

def search(self, value):
"""Search the vertical navigation menu.
Clear the input field afterward, so it does not interfere with the regular navigation menu.
:param str value: search query
:return: list of search results as strings
"""
super().search(value)
results = self._wait_for_results(results_widget=self.items)
self._ensure_search_is_cleared()
return results


class SatVerticalNavigation(VerticalNavigation):
"""The Patternfly Vertical navigation."""

Expand Down

0 comments on commit da56054

Please sign in to comment.