1- from galaxy_test .base .workflow_fixtures import WORKFLOW_WITH_OUTPUT_COLLECTION
1+ from galaxy_test .base .workflow_fixtures import (
2+ WORKFLOW_KEEP_SUCCESSFUL_DATASETS ,
3+ WORKFLOW_KEEP_SUCCESSFUL_DATASETS_TEST_DATA ,
4+ WORKFLOW_WITH_OUTPUT_COLLECTION ,
5+ )
26from .framework import (
7+ managed_history ,
38 retry_assertion_during_transitions ,
49 selenium_test ,
510 SeleniumTestCase ,
@@ -17,29 +22,9 @@ def test_job_details(self):
1722 WORKFLOW_WITH_OUTPUT_COLLECTION , history_id = history_id , assert_ok = True , wait = True
1823 )
1924
20- # open invocations panel
21- self .home ()
22- gx_selenium_context .components .invocations .activity .wait_for_and_click ()
23-
24- invocations = gx_selenium_context .components .invocations
25- invocations .invocations_panel_list .wait_for_visible ()
26-
27- @retry_assertion_during_transitions
28- def assert_has_row ():
29- invocations .invocations_panel_list_items .wait_for_visible ()
30- invocation_rows = invocations .invocations_panel_list_items .all ()
31- assert len (invocation_rows ) > 0
32- return invocation_rows [0 ]
33-
34- assert_has_row ()
35-
36- invocations .state_details .assert_absent ()
37- details = invocations .invocations_panel_list_items .all ()[0 ]
38- details .click ()
39- invocations .state_details .wait_for_visible ()
25+ self .invocation_open_latest ()
4026
41- # close invocations panel
42- gx_selenium_context .components .invocations .activity .wait_for_and_click ()
27+ invocations = self .components .invocations
4328
4429 @retry_assertion_during_transitions
4530 def assert_progress_steps_note_contains (text ):
@@ -77,3 +62,81 @@ def assert_progress_steps_note_contains(text):
7762 invocations .step_output_collection_element_identifier (element_identifier = "forward" ).wait_for_and_click ()
7863 datatype = invocations .step_output_collection_element_datatype (order_index = "1" ).wait_for_text ()
7964 assert datatype == "txt"
65+
66+ @selenium_test
67+ @managed_history # failed job messes with some history wait code we probably shouldn't be using
68+ def test_invocation_step_jobs_with_failed_jobs (self ):
69+ """Test invocation step jobs view with mixed successful and failed jobs.
70+
71+ This test verifies:
72+ - Job state counters (ok and error) display correctly for steps with mixed job states
73+ - Filtering by failed jobs works correctly
74+ - Debug tab shows only failed steps
75+ - Failed steps can be expanded in debug view
76+ """
77+ history_id = self .current_history_id ()
78+ self .workflow_populator .run_workflow (
79+ WORKFLOW_KEEP_SUCCESSFUL_DATASETS ,
80+ test_data = WORKFLOW_KEEP_SUCCESSFUL_DATASETS_TEST_DATA ,
81+ history_id = history_id ,
82+ assert_ok = False ,
83+ )
84+
85+ # Open the first invocation
86+ self .invocation_open_latest ()
87+
88+ # Navigate to Steps tab
89+ invocations = self .components .invocations
90+ invocations .invocation_tab (label = "Steps" ).wait_for_and_click ()
91+
92+ # Click on a step with multiple mixed failed and successful jobs
93+ invocations .step_details (order_index = "1" ).wait_for_and_click ()
94+ invocations .step_job_details (order_index = "1" ).wait_for_visible ()
95+
96+ # Verify job state counters
97+ okay_counter = invocations .step_job_details_state_counter (state = "ok" ).wait_for_visible ()
98+ failed_counter = invocations .step_job_details_state_counter (state = "error" ).wait_for_visible ()
99+ assert okay_counter .get_attribute ("data-count" ) == "1"
100+ assert failed_counter .get_attribute ("data-count" ) == "1"
101+ self .screenshot ("invocation_steps_view_with_failed_jobs" )
102+
103+ # Filter by failed jobs
104+ invocations .step_job_details_state_counter (state = "error" ).wait_for_and_click ()
105+ self .screenshot ("invocation_steps_view_with_failed_jobs_failed_jobs_list" )
106+
107+ # Navigate to Debug tab
108+ invocations .invocation_tab (label = "Debug" ).wait_for_and_click ()
109+
110+ # Verify the failed step appears here and the successful step doesn't
111+ self .screenshot ("invocation_steps_view_with_failed_jobs_debug_landing" )
112+ invocations .step_title (order_index = 1 ).wait_for_and_click ()
113+ invocations .step_title (order_index = 2 ).assert_absent ()
114+ self .screenshot ("invocation_steps_view_with_failed_jobs_debug_job_expanded" )
115+
116+ def invocation_open_latest (self ):
117+ # TODO: migrate retry_assertion_during_transitions to navigates_galaxy.py so this
118+ # can be moved there.
119+
120+ # open invocations panel
121+ self .home ()
122+ self .components .invocations .activity .wait_for_and_click ()
123+
124+ invocations = self .components .invocations
125+ invocations .invocations_panel_list .wait_for_visible ()
126+
127+ @retry_assertion_during_transitions
128+ def assert_has_row ():
129+ invocations .invocations_panel_list_items .wait_for_visible ()
130+ invocation_rows = invocations .invocations_panel_list_items .all ()
131+ assert len (invocation_rows ) > 0
132+ return invocation_rows [0 ]
133+
134+ assert_has_row ()
135+
136+ invocations .state_details .assert_absent ()
137+ details = invocations .invocations_panel_list_items .all ()[0 ]
138+ details .click ()
139+ invocations .state_details .wait_for_visible ()
140+
141+ # close invocations panel
142+ self .components .invocations .activity .wait_for_and_click ()
0 commit comments