@@ -83,20 +83,45 @@ def _take_screenshot(self, name_suffix):
8383 def _get_current_weighted_average (self ):
8484 """Extract and return the current weighted average from the result page."""
8585 try :
86+ # Take screenshot to debug what we're seeing
87+ self ._take_screenshot ("result_page_before_extract_average" )
88+
89+ # Make sure we are on the result page
90+ self .wait_long .until (
91+ EC .visibility_of_element_located ((By .CSS_SELECTOR , self .RESULT_PAGE_CONTAINER_SELECTOR ))
92+ )
93+
94+ # Wait for average display element
8695 current_avg_element = self .wait_long .until (
87- EC .presence_of_element_located ((By .CSS_SELECTOR , self .CURRENT_AVERAGE_DISPLAY_SELECTOR ))
96+ EC .visibility_of_element_located ((By .CSS_SELECTOR , self .CURRENT_AVERAGE_DISPLAY_SELECTOR ))
8897 )
98+
99+ # Small delay to make sure text is fully loaded/rendered
100+ time .sleep (0.2 )
101+
89102 current_avg_text = current_avg_element .text .strip ()
90103 logger .info (f"Current average text found: '{ current_avg_text } '" )
91104
92105 # Extract the numeric value using regex - looking for decimal number
106+ # Example text: "Promedio actual: 1.8"
93107 match = re .search (r'(\d+\.\d+)' , current_avg_text )
94108 if match :
95109 current_avg = float (match .group (1 ))
96110 logger .info (f"Extracted current average: { current_avg } " )
97111 return current_avg
98112 else :
99113 logger .error (f"Failed to extract numeric average from text: '{ current_avg_text } '" )
114+ # Try an alternative approach - get the raw text content
115+ raw_text = current_avg_element .get_attribute ('textContent' ).strip ()
116+ logger .info (f"Raw text content: '{ raw_text } '" )
117+
118+ # Try to find any decimal number in the raw text
119+ alt_match = re .search (r'(\d+\.\d+)' , raw_text )
120+ if alt_match :
121+ current_avg = float (alt_match .group (1 ))
122+ logger .info (f"Extracted current average from raw text: { current_avg } " )
123+ return current_avg
124+
100125 self ._take_screenshot ("average_extraction_failed" )
101126 self .fail (f"Could not extract numeric average from: '{ current_avg_text } '" )
102127
@@ -170,87 +195,140 @@ def _initial_setup(self):
170195 logger .error (f"An unexpected error occurred during initial setup: { e } " , exc_info = True )
171196 self ._take_screenshot ("initial_setup_error" )
172197 self .fail (f"Unexpected error during initial setup: { e } " )
173-
198+
174199 def _add_grade_and_percentage (self , grade , percentage ):
175200 if not hasattr (self , 'driver' ) or not self .driver :
176201 logger .error ("Driver not available in _add_grade_and_percentage." )
177202 self .fail ("Driver not available." )
178203 return
179204
205+ # First check if we're on the result page and navigate back if needed
180206 on_result_page = False
181207 try :
182- # Check if the result page container is present
183208 if self .driver .find_element (By .CSS_SELECTOR , self .RESULT_PAGE_CONTAINER_SELECTOR ).is_displayed ():
184209 on_result_page = True
185210 except NoSuchElementException :
186- on_result_page = False # Not on result page
211+ on_result_page = False
187212
188213 if on_result_page :
189- logger .info ("Currently on result page (detected by element presence) , navigating back to home to add grades." )
214+ logger .info ("Currently on result page, navigating back to home to add grades." )
190215 try :
216+ # First try with the CSS selector
191217 nav_back_button = self .wait_short .until (
192218 EC .element_to_be_clickable ((By .CSS_SELECTOR , self .NAV_BACK_BUTTON_SELECTOR ))
193219 )
194220 logger .info ("Found back button using CSS selector in _add_grade_and_percentage." )
195221 except TimeoutException :
196- logger .info ("CSS selector failed for back button in _add_grade_and_percentage, trying XPath..." )
197- nav_back_button = self .wait_long .until (
198- EC .element_to_be_clickable ((By .XPATH , self .NAV_BACK_BUTTON_XPATH ))
199- )
200- logger .info ("Found back button using XPath selector in _add_grade_and_percentage." )
201-
222+ try :
223+ # Then try with XPath
224+ logger .info ("CSS selector failed for back button in _add_grade_and_percentage, trying XPath..." )
225+ nav_back_button = self .wait_long .until (
226+ EC .element_to_be_clickable ((By .XPATH , self .NAV_BACK_BUTTON_XPATH ))
227+ )
228+ logger .info ("Found back button using XPath selector in _add_grade_and_percentage." )
229+ except TimeoutException :
230+ # As a last resort, try to find any buttons in the nav bar
231+ logger .info ("XPath also failed. Looking for any button in the nav bar..." )
232+ nav_bar = self .wait_long .until (
233+ EC .presence_of_element_located ((By .CSS_SELECTOR , "nav.nav-bar" ))
234+ )
235+ nav_buttons = nav_bar .find_elements (By .TAG_NAME , "button" )
236+ if nav_buttons :
237+ nav_back_button = nav_buttons [0 ] # First button in nav bar is usually back
238+ logger .info ("Using first button found in nav bar" )
239+ else :
240+ logger .error ("No buttons found in nav bar" )
241+ self ._take_screenshot ("no_buttons_in_nav_bar_add_grade" )
242+ self .fail ("No buttons found in nav bar when trying to navigate back" )
243+
244+ # Click the back button once found
202245 nav_back_button .click ()
203246 self .wait_long .until (EC .presence_of_element_located ((By .CSS_SELECTOR , self .HOME_CONTAINER_SELECTOR )))
204- logger .info ("Navigated back to home page." )
247+ logger .info ("Successfully navigated back to home page." )
248+
249+ # Take a small pause to ensure the UI is fully loaded
250+ time .sleep (0.5 )
205251
252+ # Now we're on the home page
253+ # Take a screenshot of the current state for debugging
254+ self ._take_screenshot ("before_adding_grade" )
255+
256+ # Find all grade rows currently in the UI
206257 grade_rows = self .driver .find_elements (By .CSS_SELECTOR , self .GRADES_LIST_ITEM_SELECTOR )
207- if not grade_rows :
208- logger .warning ("No grade rows found. Attempting to add one by clicking the global 'Add Grade' button." )
209- self ._take_screenshot ("no_grade_rows_found" )
258+ logger .info (f"Found { len (grade_rows )} grade rows before adding." )
259+
260+ # First check if we need to add a new row
261+ need_new_row = True
262+ if grade_rows :
263+ # Check if the last row is empty (which means we can use it)
264+ last_row = grade_rows [- 1 ]
210265 try :
211- # This assumes ADD_GRADE_BUTTON_SELECTOR is the button that adds a new empty row for input
212- add_button_global = self .wait_long .until (EC .element_to_be_clickable ((By .CSS_SELECTOR , self .ADD_GRADE_BUTTON_SELECTOR )))
213- add_button_global .click ()
214- time .sleep (0.5 ) # Allow time for the row to be added dynamically
215- grade_rows = self .driver .find_elements (By .CSS_SELECTOR , self .GRADES_LIST_ITEM_SELECTOR )
216- if not grade_rows :
217- logger .error ("Still no grade rows found after attempting to add one." )
218- self ._take_screenshot ("failed_to_add_initial_row" )
219- self .fail ("Still no grade rows found after attempting to add one." )
220- return
221- logger .info (f"Successfully added an initial grade row. Now { len (grade_rows )} rows." )
222- except Exception as ex :
223- logger .error (f"Failed to create an initial grade row by clicking add button: { ex } " , exc_info = True )
224- self ._take_screenshot ("create_initial_row_exception" )
225- self .fail (f"Failed to create an initial grade row: { ex } " )
226- return
227-
266+ grade_input = last_row .find_element (By .CSS_SELECTOR , self .GRADE_INPUT_SELECTOR )
267+ percentage_input = last_row .find_element (By .CSS_SELECTOR , self .PERCENTAGE_INPUT_SELECTOR )
268+
269+ grade_value = grade_input .get_attribute ("value" )
270+ percentage_value = percentage_input .get_attribute ("value" )
271+
272+ # If both inputs are empty, we can use this row
273+ if not grade_value and not percentage_value :
274+ need_new_row = False
275+ logger .info ("Found empty row to use for new grade entry." )
276+ except NoSuchElementException :
277+ # If we can't find inputs in the last row, we'll add a new one
278+ logger .warning ("Last row doesn't have expected input elements." )
279+ need_new_row = True
280+
281+ # If we need a new row or there are no rows, add one
282+ if need_new_row or not grade_rows :
283+ logger .info ("Adding a new grade row..." )
284+ add_button = self .wait_long .until (EC .element_to_be_clickable ((By .CSS_SELECTOR , self .ADD_GRADE_BUTTON_SELECTOR )))
285+ add_button .click ()
286+ time .sleep (0.5 ) # Wait for the row to be added
287+
288+ # Refresh the list of grade rows
289+ grade_rows = self .driver .find_elements (By .CSS_SELECTOR , self .GRADES_LIST_ITEM_SELECTOR )
290+ if not grade_rows :
291+ logger .error ("Failed to add grade row - no rows found after clicking 'Add' button" )
292+ self ._take_screenshot ("failed_to_add_grade_row" )
293+ self .fail ("Failed to add grade row - no rows found after clicking 'Add' button" )
294+
295+ # Now use the last row to add our grade
228296 last_row = grade_rows [- 1 ]
229- logger .info (f"Targeting the last of { len (grade_rows )} grade rows for input. " )
230-
297+ logger .info (f"Using the last of { len (grade_rows )} rows to add grade: { grade } , percentage: { percentage } " )
298+
231299 try :
232300 grade_input_element = last_row .find_element (By .CSS_SELECTOR , self .GRADE_INPUT_SELECTOR )
233301 percentage_input_element = last_row .find_element (By .CSS_SELECTOR , self .PERCENTAGE_INPUT_SELECTOR )
302+
303+ # Clear and enter the grade and percentage
304+ grade_input_element .clear ()
305+ grade_input_element .send_keys (str (grade ))
306+ percentage_input_element .clear ()
307+ percentage_input_element .send_keys (str (percentage ))
308+
309+ # Take screenshot after entering values
310+ self ._take_screenshot (f"after_entering_grade_{ grade } _percent_{ percentage } " )
311+
312+ # Click the add button to confirm this grade
313+ add_button = self .wait_long .until (EC .element_to_be_clickable ((By .CSS_SELECTOR , self .ADD_GRADE_BUTTON_SELECTOR )))
314+ add_button .click ()
315+ logger .info (f"Clicked 'Add' button after entering grade: { grade } , percentage: { percentage } " )
316+
317+ # Allow time for the UI to update
318+ time .sleep (0.5 )
319+
320+ # Verify the grade was added by checking for more rows or for values in the inputs
321+ new_grade_rows = self .driver .find_elements (By .CSS_SELECTOR , self .GRADES_LIST_ITEM_SELECTOR )
322+ logger .info (f"After adding: { len (new_grade_rows )} grade rows (previously { len (grade_rows )} )" )
323+
324+ # Take screenshot after adding grade
325+ self ._take_screenshot ("after_adding_grade" )
326+
234327 except NoSuchElementException as e :
235- logger .error (f"Could not find grade or percentage input in the last row: { e } " )
236- logger .info (f"HTML of last row: { last_row .get_attribute ('outerHTML' )} " )
237- self ._take_screenshot ("input_not_found_in_last_row" )
238- self .fail (f"Input elements not found in the last row: { e } " )
328+ logger .error (f"Could not find input elements in the grade row: { e } " )
329+ self ._take_screenshot ("input_elements_not_found" )
330+ self .fail (f"Input elements not found: { e } " )
239331 return
240-
241- # Assuming ADD_GRADE_BUTTON_SELECTOR is the button to confirm/add the currently entered grade,
242- # not necessarily the one that creates a new blank row if that's different.
243- # If the app auto-adds a new row upon filling the last one and clicking a general "add" button, this is fine.
244- add_button = self .wait_long .until (EC .element_to_be_clickable ((By .CSS_SELECTOR , self .ADD_GRADE_BUTTON_SELECTOR )))
245-
246- grade_input_element .clear ()
247- grade_input_element .send_keys (str (grade ))
248- percentage_input_element .clear ()
249- percentage_input_element .send_keys (str (percentage ))
250-
251- add_button .click ()
252- logger .info (f"Clicked 'Agregar nota' after filling grade: { grade } , percentage: { percentage } into the last available row." )
253- time .sleep (0.5 ) # Brief pause for UI to update, e.g., adding a new empty row
254332
255333 def test_us04_verify_calculation_of_current_weighted_average (self ):
256334 test_name = self ._testMethodName
@@ -322,7 +400,7 @@ def test_us04_verify_calculation_of_current_weighted_average(self):
322400 logger .warning ("CSS selector failed for back button in step 1, trying XPath with more wait time..." )
323401 # Take debug screenshot
324402 self ._take_screenshot ("css_selector_failed_step1" )
325- # Try a more verbose approach to locate the button
403+ # Try a more verbose approach to locate the button
326404 try :
327405 # First, check if there's a nav bar
328406 nav_bar = self .wait_long .until (
0 commit comments