Skip to content

Commit 242e742

Browse files
committed
pf5 on job_invocation wizard
1 parent 910225a commit 242e742

7 files changed

Lines changed: 354 additions & 52 deletions

File tree

airgun/entities/host_new.py

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@
33
from navmazing import NavigateToSibling
44
from wait_for import wait_for
55

6+
from airgun.entities.all_hosts import AllHostsEntity
67
from airgun.entities.host import HostEntity
78
from airgun.navigation import NavigateStepWithWait as NavigateStep, navigator
9+
from airgun.views.all_hosts import AllHostsTableView
810
from airgun.views.cloud_insights import RemediateSummary
911
from airgun.views.fact import HostFactView
10-
from airgun.views.host import HostsView as LegacyHostsView
12+
from airgun.views.host import HostsJobInvocationStatusView, HostsView as LegacyHostsView
1113
from airgun.views.host_new import (
1214
AllAssignedRolesView,
1315
ContainerfileInstallCommandView,
1416
EditAnsibleRolesView,
1517
EditSystemPurposeView,
1618
EnableTracerView,
17-
HostsView,
1819
InstallPackagesView,
1920
ManageHostCollectionModal,
2021
ManageHostStatusesView,
@@ -351,6 +352,72 @@ def schedule_job(self, entity_name, values):
351352
view.fill(values)
352353
view.submit.click()
353354

355+
def schedule_remote_job(self, entities_list, values, timeout=60, wait_for_results=True):
356+
"""Apply Schedule Remote Job action to the hosts names in entities_list using PF5 UI.
357+
358+
For multiple hosts, uses AllHostsEntity helper to select checkboxes, then clicks
359+
"Schedule a job" button which opens the wizard with hosts pre-selected.
360+
361+
:param entities_list: The host names to apply the remote job.
362+
:param values: the values to fill The Job invocation view.
363+
:param timeout: The time to wait for the job to finish.
364+
:param wait_for_results: Whether to wait for the job to finish execution.
365+
366+
:returns: The job invocation status view values
367+
"""
368+
if len(entities_list) == 1:
369+
# Single host - use the host details page approach
370+
entity_name = entities_list[0]
371+
details_view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
372+
self.browser.plugin.ensure_page_safe()
373+
details_view.wait_displayed()
374+
# Click the Schedule a job dropdown
375+
self.browser.wait_for_element(details_view.schedule_job, exception=False)
376+
details_view.schedule_job.fill('Schedule a job')
377+
# The job invocation form appears in the same browser context
378+
view = JobInvocationCreateView(self.browser)
379+
self.browser.plugin.ensure_page_safe()
380+
else:
381+
# Multiple hosts - use AllHostsEntity helper to navigate and select hosts
382+
# This helper handles: clearing previous selections, searching, selecting checkboxes
383+
# and returns AllHostsTableView with selected hosts
384+
hosts_view = AllHostsEntity.all_hosts_navigate_and_select_hosts_helper(
385+
self, host_names=entities_list
386+
)
387+
388+
# After selecting hosts, click the "Schedule a job" button
389+
# This button appears dynamically after hosts are selected
390+
schedule_button_locator = ".//button[contains(., 'Schedule a job') or @data-ouia-component-id='schedule-a-job-dropdown']"
391+
wait_for(
392+
lambda: hosts_view.browser.element(schedule_button_locator, check_visibility=True),
393+
timeout=10,
394+
delay=0.5,
395+
handle_exception=True,
396+
)
397+
schedule_button = hosts_view.browser.element(schedule_button_locator)
398+
hosts_view.browser.click(schedule_button)
399+
400+
# The job invocation form should now open with hosts pre-selected
401+
view = JobInvocationCreateView(self.browser)
402+
self.browser.plugin.ensure_page_safe()
403+
# Wait for the wizard to be displayed
404+
view.wait_displayed()
405+
406+
# Fill the form with provided values
407+
view.fill(values)
408+
# Wait for form to be fully filled and ready for submission
409+
self.browser.plugin.ensure_page_safe()
410+
view.submit.click()
411+
view.flash.assert_no_error()
412+
view.flash.dismiss()
413+
# Wait for status view to appear after job submission
414+
status_view = HostsJobInvocationStatusView(self.browser)
415+
self.browser.plugin.ensure_page_safe()
416+
status_view.wait_displayed()
417+
if wait_for_results:
418+
status_view.wait_for_result(timeout=timeout)
419+
return status_view.read()
420+
354421
def run_job(self, entity_name):
355422
"""Run a job on selected host"""
356423
view = self.navigate_to(self, 'NewDetails', entity_name=entity_name)
@@ -1228,7 +1295,7 @@ def get_content_view_envs(self, entity_name):
12281295
class ShowAllHosts(NavigateStep):
12291296
"""Navigate to new UI All Hosts page"""
12301297

1231-
VIEW = HostsView
1298+
VIEW = AllHostsTableView
12321299

12331300
def step(self, *args, **kwargs):
12341301
self.view.menu.select('Hosts', 'All Hosts')
@@ -1249,6 +1316,7 @@ def prerequisite(self, *args, **kwargs):
12491316

12501317
def step(self, *args, **kwargs):
12511318
entity_name = kwargs.get('entity_name')
1319+
12521320
self.parent.search(entity_name)
12531321
self.parent.table.row(name=entity_name)['Name'].widget.click()
12541322

airgun/entities/job_invocation.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ def run(self, values):
2222
"""Run specific job"""
2323
view = self.navigate_to(self, 'Run')
2424
view.fill(values)
25-
view.submit.expander.click()
26-
self.browser.wait_for_element(view.submit.submit, exception=False)
27-
view.submit.click()
25+
view.submit.click() # PF5 wizard: submit.click() handles everything
2826

2927
def search(self, value):
3028
"""Search for specific job invocation"""
@@ -40,6 +38,7 @@ def wait_job_invocation_state(self, entity_name, host_name, expected_state='succ
4038
"""Check job invocation state from table view"""
4139
view = self.navigate_to(self, 'All')
4240
view.search(f'host = {host_name}')
41+
4342
wait_for(
4443
lambda: view.table.row(description=entity_name)['Status'].read() == expected_state,
4544
timeout=300,

airgun/views/all_hosts.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ class AllHostsTableView(BaseLoggedInView, SearchableViewMixinPF4):
106106
locator='//li[contains(@class, "pf-v5-c-menu__list-item")]//button[span/span[text()="Change associations"]]/following-sibling::div[contains(@class, "pf-v5-c-menu")]'
107107
)
108108

109+
# Additional action buttons
110+
schedule_a_job = PF5OUIADropdown('schedule-a-job-dropdown')
111+
109112
table_loading = Text('//h5[normalize-space(.)="Loading"]')
110113
no_results = Text('//h5[normalize-space(.)="No Results"]')
111114
manage_columns = PF5Button('Manage columns')

airgun/views/common.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,3 +772,18 @@ def __init__(self, parent, logger=None):
772772
"""Expand the selected wizard step"""
773773
View.__init__(self, parent, logger=logger)
774774
self.expander.click()
775+
776+
777+
class PF5WizardStepView(View):
778+
"""PF5 Wizard step - doesn't use expanders, uses wizard navigation instead.
779+
780+
The PF5 wizard pattern navigates between steps using Next/Back buttons
781+
in the footer, not by clicking expander buttons. Steps are already visible
782+
when you're on that step.
783+
"""
784+
785+
def __init__(self, parent, logger=None):
786+
"""Initialize PF5 wizard step without clicking expander."""
787+
View.__init__(self, parent, logger=logger)
788+
# PF5 wizards don't have expanders - steps are navigated via Next/Back buttons
789+
# The step is already visible when active

airgun/views/host_new.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ class HostsView(BaseLoggedInView, SearchableViewMixinPF4):
268268

269269
@property
270270
def is_displayed(self):
271-
return self.title.is_displayed
271+
return self.browser.wait_for_element(self.title, exception=False) is not None
272272

273273

274274
class BreadcrumbSwitcher(Widget):

0 commit comments

Comments
 (0)