Skip to content

Commit 22b89d7

Browse files
test: Enhance US03 tests with alert verification for percentage sum > 100%
1 parent b3a8679 commit 22b89d7

File tree

1 file changed

+88
-80
lines changed

1 file changed

+88
-80
lines changed

tests/us3.py

Lines changed: 88 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ class US03Tests(unittest.TestCase):
1717
PERCENTAGE_INPUT_SELECTOR = "input.home__input[placeholder='0'][type='number']"
1818
ADD_GRADE_BUTTON_SELECTOR = "button.home__add-button"
1919
GRADES_LIST_ITEM_SELECTOR = "div.home__grades-container > div.home__grade-row"
20-
REMAINING_PERCENTAGE_DISPLAY_SELECTOR = "div.home__results-card p.home__card-text span"
20+
CALCULATE_BUTTON_SELECTOR = "button.home__calculate-button" # Added
21+
ALERT_TITLE_SELECTOR = "div.alert__title" # Added
22+
ALERT_MESSAGE_SELECTOR = "div.alert__message" # Added
23+
ALERT_CONFIRM_BUTTON_SELECTOR = "div.alert__actions button.alert__button" # General confirm, can be more specific if needed
2124

2225
FIRST_TIME_ALERT_BUTTON_SELECTOR = ".alert__button.alert__button--single"
2326
ALERT_OVERLAY_SELECTOR = "div.alert__overlay"
@@ -126,16 +129,38 @@ def _add_grade_and_percentage(self, grade, percentage):
126129
self.fail("Driver not available.")
127130
return
128131

132+
# Find all grade input rows. The last one is the one we want to fill.
133+
# If it's the first grade, it's the only row.
134+
# If we've added one, a new empty row is typically added by the app, so we target that.
135+
136+
# Click "Agregar nota" first to ensure a new empty row is available if needed,
137+
# or to use the existing one if it's the first entry.
138+
# This logic might need adjustment based on how `handleAddGrade` in home.jsx works.
139+
# For now, assume we always fill the *last* available input row.
140+
141+
# If it's not the first grade being added in the test sequence, click "Agregar nota"
142+
# to generate a new row for this entry.
143+
# This assumes that _add_grade_and_percentage is called for each new grade entry
144+
# and the app adds a new row template upon clicking "Agregar nota" *after* filling the previous.
145+
146+
# Let's refine: The "Agregar nota" button adds a new *blank* row.
147+
# We should fill the *current last* row's inputs, then click "Agregar nota"
148+
# if we intend to add *another* one after this.
149+
# The current _add_grade_and_percentage is designed to fill inputs and then click "Agregar nota".
150+
# This implies "Agregar nota" serves dual purpose: commit current and prepare next.
151+
# This seems to be the behavior from US01/US02.
152+
129153
grade_rows = self.driver.find_elements(By.CSS_SELECTOR, self.GRADES_LIST_ITEM_SELECTOR)
130154
if not grade_rows:
131155
logger.error("No grade rows found to add grade and percentage.")
132156
self._take_screenshot("no_grade_rows_found")
133157
self.fail("No grade rows found.")
134158
return
135159

136-
last_row = grade_rows[-1]
160+
last_row = grade_rows[-1] # Target the last row for input
137161
logger.info(f"Targeting the last of {len(grade_rows)} grade rows for input.")
138162

163+
139164
try:
140165
grade_input_element = last_row.find_element(By.CSS_SELECTOR, self.GRADE_INPUT_SELECTOR)
141166
percentage_input_element = last_row.find_element(By.CSS_SELECTOR, self.PERCENTAGE_INPUT_SELECTOR)
@@ -146,109 +171,92 @@ def _add_grade_and_percentage(self, grade, percentage):
146171
self.fail("Input elements not found in the last row.")
147172
return
148173

174+
# The "Agregar nota" button is outside the rows, so it's found globally.
149175
add_button = self.wait_long.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.ADD_GRADE_BUTTON_SELECTOR)))
150176

151177
grade_input_element.clear()
152178
grade_input_element.send_keys(str(grade))
153179
percentage_input_element.clear()
154180
percentage_input_element.send_keys(str(percentage))
155181

182+
# Click "Agregar nota" AFTER filling the inputs.
183+
# This should add the current grade and potentially prepare a new row.
156184
add_button.click()
157-
logger.info(f"Clicked 'Agregar nota' after attempting to add grade: {grade}, percentage: {percentage} to the last row.")
158-
# Wait for UI to update, especially if new rows are added dynamically.
185+
logger.info(f"Clicked \'Agregar nota\' after filling grade: {grade}, percentage: {percentage} into the last available row.")
186+
187+
# Wait for UI to update, e.g., for a new row to be added if that's the behavior.
159188
# A more robust wait would be for the number of rows to change or for a specific element to appear.
160189
time.sleep(0.5) # Small delay for React state updates
161190

162-
def _get_remaining_percentage(self):
163-
cleaned_text = "" # Initialize cleaned_text
164-
try:
165-
# Wait for the element to be present and contain some text
166-
percentage_element = self.wait_long.until(
167-
EC.presence_of_element_located((By.CSS_SELECTOR, self.REMAINING_PERCENTAGE_DISPLAY_SELECTOR))
168-
)
169-
# Add a small delay or check for text to be non-empty if necessary
170-
time.sleep(0.2) # give a brief moment for text to update
171-
172-
# Attempt to get text, retry if it's empty initially due to rendering delays
173-
text_value = percentage_element.text.strip()
174-
attempts = 0
175-
while text_value == "" and attempts < 5: # Retry if empty
176-
time.sleep(0.3)
177-
text_value = percentage_element.text.strip()
178-
attempts += 1
179-
180-
logger.info(f"Raw remaining percentage text: '{text_value}'")
181-
if not text_value: # If still empty after retries
182-
logger.warning("Remaining percentage text is empty after retries.")
183-
self._take_screenshot("empty_remaining_percentage")
184-
return "Error: Empty Value" # Or raise an error
185-
186-
# Assuming the text is like "XX %" or "XX%", we remove "%" and convert to float
187-
# If it's just "XX", this will also work.
188-
cleaned_text = text_value.replace('%', '').strip()
189-
return float(cleaned_text)
190-
except TimeoutException:
191-
logger.error(f"Timeout waiting for remaining percentage display element: {self.REMAINING_PERCENTAGE_DISPLAY_SELECTOR}")
192-
self._take_screenshot("remaining_percentage_timeout")
193-
return "Error: Timeout" # Or raise an error
194-
except ValueError:
195-
logger.error(f"Could not convert remaining percentage text '{cleaned_text}' to float.") # cleaned_text is now defined
196-
self._take_screenshot("remaining_percentage_value_error")
197-
return "Error: Conversion" # Or raise an error
198-
except Exception as e:
199-
logger.error(f"Error getting remaining percentage: {e}")
200-
self._take_screenshot("get_remaining_percentage_error")
201-
return "Error: General" # Or raise an error
202-
203-
# US03: Calculo del porcentaje faltante
204-
def test_us03_verify_calculation_of_remaining_percentage(self):
191+
# US03: Verify alert for percentage sum > 100%
192+
def test_us03_verify_percentage_sum_alert(self):
205193
test_name = self._testMethodName
206194
logger.info(f"Running test: {test_name}")
207195

208196
try:
209-
# 1. Initial state: Verify remaining percentage is 100%
210-
logger.info("Verifying initial remaining percentage.")
211-
initial_remaining = self._get_remaining_percentage()
212-
self.assertEqual(initial_remaining, 100.0,
213-
f"Initial remaining percentage expected 100.0, but got {initial_remaining}")
214-
logger.info(f"Initial remaining percentage is correct: {initial_remaining}%")
197+
# 1. Add grades with percentages summing > 100%
198+
logger.info("Adding first grade (70%).")
199+
self._add_grade_and_percentage("3.0", "70")
200+
201+
# The previous _add_grade_and_percentage clicks "Agregar nota",
202+
# which should make a new row available for the next grade.
203+
logger.info("Adding second grade (40%). Total percentage should be 110%.")
204+
self._add_grade_and_percentage("4.0", "40")
205+
# After this, we should have two rows with data, and possibly a third empty template row.
206+
207+
# 2. Click "Calcular" button
208+
logger.info(f"Clicking \'Calcular\' button with selector: {self.CALCULATE_BUTTON_SELECTOR}")
209+
calculate_button = self.wait_long.until(
210+
EC.element_to_be_clickable((By.CSS_SELECTOR, self.CALCULATE_BUTTON_SELECTOR))
211+
)
212+
calculate_button.click()
213+
logger.info("\'Calcular\' button clicked.")
214+
215+
# 3. Verify the alert is displayed with correct title and message
216+
logger.info("Verifying alert for percentage sum > 100%.")
217+
218+
alert_title_element = self.wait_long.until(
219+
EC.visibility_of_element_located((By.CSS_SELECTOR, self.ALERT_TITLE_SELECTOR))
220+
)
221+
alert_title_text = alert_title_element.text
222+
expected_title = "La suma de los porcentajes es mayor al 100%"
223+
self.assertEqual(alert_title_text, expected_title,
224+
f"Alert title expected \'{expected_title}\', but got \'{alert_title_text}\'")
225+
logger.info(f"Alert title is correct: \'{alert_title_text}\'")
215226

216-
# 2. Add one grade and verify
217-
logger.info("Adding first grade (20%).")
218-
self._add_grade_and_percentage("3.0", "20")
219-
# It might take a moment for the calculation to update
220-
time.sleep(0.5) # Wait for calculation update
221-
remaining_after_first_grade = self._get_remaining_percentage()
222-
self.assertEqual(remaining_after_first_grade, 80.0,
223-
f"Remaining percentage after 1st grade (20%) expected 80.0, but got {remaining_after_first_grade}")
224-
logger.info(f"Remaining percentage after 1st grade (20%) is correct: {remaining_after_first_grade}%")
227+
alert_message_element = self.wait_long.until(
228+
EC.visibility_of_element_located((By.CSS_SELECTOR, self.ALERT_MESSAGE_SELECTOR))
229+
)
230+
alert_message_text = alert_message_element.text
231+
expected_message = "Por favor verifica los porcentajes de las notas ingresadas, para que la suma sea menor o igual a 100%."
232+
self.assertEqual(alert_message_text, expected_message,
233+
f"Alert message expected \'{expected_message}\', but got \'{alert_message_text}\'")
234+
logger.info(f"Alert message is correct: \'{alert_message_text}\'")
225235

226-
# 3. Add a second grade and verify
227-
logger.info("Adding second grade (30%). Total 50%.")
228-
self._add_grade_and_percentage("4.0", "30")
229-
time.sleep(0.5) # Wait for calculation update
230-
remaining_after_second_grade = self._get_remaining_percentage()
231-
self.assertEqual(remaining_after_second_grade, 50.0,
232-
f"Remaining percentage after 2nd grade (total 50%) expected 50.0, but got {remaining_after_second_grade}")
233-
logger.info(f"Remaining percentage after 2nd grade (total 50%) is correct: {remaining_after_second_grade}%")
236+
# 4. Close the alert
237+
alert_confirm_button = self.wait_long.until(
238+
EC.element_to_be_clickable((By.CSS_SELECTOR, self.ALERT_CONFIRM_BUTTON_SELECTOR))
239+
)
240+
# Based on alert.jsx, if showCancel is false (which it is for this alert),
241+
# the confirm button will have 'alert__button--single'
242+
# We can use a more general selector for the button within alert__actions
243+
alert_confirm_button.click()
244+
logger.info("Alert confirm button clicked.")
234245

235-
# 4. Add a third grade to make total 100% and verify
236-
logger.info("Adding third grade (50%). Total 100%.")
237-
self._add_grade_and_percentage("5.0", "50")
238-
time.sleep(0.5) # Wait for calculation update
239-
remaining_after_third_grade = self._get_remaining_percentage()
240-
self.assertEqual(remaining_after_third_grade, 0.0,
241-
f"Remaining percentage after 3rd grade (total 100%) expected 0.0, but got {remaining_after_third_grade}")
242-
logger.info(f"Remaining percentage after 3rd grade (total 100%) is correct: {remaining_after_third_grade}%")
246+
# Verify alert is closed
247+
WebDriverWait(self.driver, 5).until(
248+
EC.invisibility_of_element_located((By.CSS_SELECTOR, self.ALERT_OVERLAY_SELECTOR))
249+
)
250+
logger.info("Alert successfully closed.")
243251

244252
except AssertionError as e:
245253
logger.error(f"AssertionError in {test_name}: {e}")
246254
self._take_screenshot(f"{test_name}_assertion_failure")
247-
raise # Re-raise the assertion error to fail the test
255+
raise
248256
except Exception as e:
249257
logger.error(f"An unexpected error occurred in {test_name}: {e}")
250258
self._take_screenshot(f"{test_name}_unexpected_error")
251-
raise # Re-raise to fail the test
259+
raise
252260

253261
logger.info(f"Test {test_name} completed successfully.")
254262

0 commit comments

Comments
 (0)