diff --git a/airgun/entities/host_new.py b/airgun/entities/host_new.py index 3878612ab..57d1f5418 100644 --- a/airgun/entities/host_new.py +++ b/airgun/entities/host_new.py @@ -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): @@ -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): diff --git a/airgun/views/ansible_variable.py b/airgun/views/ansible_variable.py index 7a24d8f3e..2aef315c8 100644 --- a/airgun/views/ansible_variable.py +++ b/airgun/views/ansible_variable.py @@ -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): diff --git a/airgun/views/common.py b/airgun/views/common.py index 3b2711001..fa4fe2414 100644 --- a/airgun/views/common.py +++ b/airgun/views/common.py @@ -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 @@ -53,21 +54,28 @@ def select_logout(self): 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) diff --git a/airgun/views/host_new.py b/airgun/views/host_new.py index d34145322..b1922f816 100644 --- a/airgun/views/host_new.py +++ b/airgun/views/host_new.py @@ -508,6 +508,10 @@ 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={ @@ -515,13 +519,19 @@ class variables(Tab): '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()