|
4 | 4 | from selenium.webdriver.common.by import By |
5 | 5 | from selenium.webdriver.support.ui import WebDriverWait |
6 | 6 | from selenium.webdriver.support import expected_conditions as EC |
7 | | -from selenium.common.exceptions import TimeoutException |
| 7 | +from selenium.common.exceptions import TimeoutException # Ensure this is imported |
| 8 | + |
| 9 | +# Configure logging |
| 10 | +import logging |
| 11 | +logger = logging.getLogger(__name__) |
| 12 | +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') |
| 13 | + |
| 14 | +class HomePageTest(StaticLiveServerTestCase): |
| 15 | + GRADE_INPUT_SELECTOR = 'input.home__input[placeholder="0.0"][type="number"]' |
| 16 | + PERCENTAGE_INPUT_SELECTOR = 'input.home__input[placeholder="0"][type="number"]' |
| 17 | + ADD_GRADE_BUTTON_SELECTOR = 'button.home__add-button' |
| 18 | + GRADES_LIST_ITEM_SELECTOR = "div.home__grades-container > div.home__grade-row" |
| 19 | + |
| 20 | + @classmethod |
| 21 | + def setUpClass(cls): |
| 22 | + super().setUpClass() |
| 23 | + # Additional setup if needed |
| 24 | + cls.driver.implicitly_wait(10) # Implicit wait for elements to be present |
| 25 | + |
| 26 | + def _initial_setup(self): |
| 27 | + self.driver.get(self.live_server_url) |
| 28 | + # No alert handling for now, as it's not in the provided production HTML |
| 29 | + # try: |
| 30 | + # WebDriverWait(self.driver, 3).until( |
| 31 | + # EC.element_to_be_clickable((By.CSS_SELECTOR, ".alert__button.alert__button--single")) |
| 32 | + # ).click() |
| 33 | + # logger.info("Initial alert handled.") |
| 34 | + # except TimeoutException: |
| 35 | + # logger.info("Initial alert not found or not clickable, proceeding.") |
8 | 36 |
|
9 | | -class TestHomePage: |
10 | | - def _initial_setup(self, driver): |
11 | | - base_url = os.environ.get('APP_URL', 'http://localhost:3000') |
12 | | - driver.get(base_url) |
13 | | - time.sleep(1) # Allow a brief moment for initial rendering |
14 | | - |
15 | | - # 1. Handle initial alert (if any) |
16 | | - try: |
17 | | - alert_button = WebDriverWait(driver, 10).until( |
18 | | - EC.element_to_be_clickable((By.CSS_SELECTOR, ".alert__button.alert__button--single")) |
19 | | - ) |
20 | | - alert_button.click() |
21 | | - # Wait for the alert to disappear or for a subsequent element if needed |
22 | | - WebDriverWait(driver, 5).until(EC.staleness_of(alert_button)) |
23 | | - print("Initial alert handled.") |
24 | | - except TimeoutException: |
25 | | - print("Initial alert not found or not clickable within 10s.") |
26 | | - except Exception as e: |
27 | | - print(f"Error clicking initial alert: {e}, proceeding.") |
28 | | - |
29 | | - # 2. Check if we are on the main page (with grade-input) or need to navigate back |
30 | 37 | try: |
31 | | - # Try to find a main page element immediately. If present, we are good. |
32 | | - WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.ID, "grade-input"))) |
33 | | - print("Already on the main page with grade input.") |
34 | | - return # Already on the correct page |
| 38 | + # Wait for the main grade input to be present |
| 39 | + self.wait_long.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.GRADE_INPUT_SELECTOR))) |
| 40 | + logger.info(f"Grade input ('{self.GRADE_INPUT_SELECTOR}') found on page load.") |
35 | 41 | except TimeoutException: |
36 | | - print("Grade input not immediately visible. Attempting navigation back from potential settings/initial page.") |
37 | | - try: |
38 | | - # If not on main page, try to click a common 'back' or 'home' button |
39 | | - # Using ".nav-bar__button" from the original test_home_page_functional_flow |
40 | | - back_button = WebDriverWait(driver, 10).until( |
41 | | - EC.element_to_be_clickable((By.CSS_SELECTOR, ".nav-bar__button")) |
42 | | - ) |
43 | | - back_button.click() |
44 | | - print("Clicked .nav-bar__button.") |
45 | | - # Wait for the main page element to ensure navigation was successful |
46 | | - WebDriverWait(driver, 10).until( |
47 | | - EC.presence_of_element_located((By.ID, "grade-input")) |
48 | | - ) |
49 | | - print("Successfully navigated to the main page with grade-input after clicking back.") |
50 | | - except TimeoutException: |
51 | | - print("Failed to find grade-input after attempting back navigation.") |
52 | | - os.makedirs("screenshots", exist_ok=True) |
53 | | - driver.save_screenshot(f"screenshots/error_initial_setup_navigation_timeout_{int(time.time())}.png") |
54 | | - raise Exception("Could not navigate to the main page with grade-input during setup.") |
55 | | - except Exception as e_nav: |
56 | | - print(f"Error during back navigation attempt: {e_nav}") |
57 | | - os.makedirs("screenshots", exist_ok=True) |
58 | | - driver.save_screenshot(f"screenshots/error_initial_setup_navigation_exception_{int(time.time())}.png") |
59 | | - raise e_nav |
60 | | - except Exception as e_main_check: |
61 | | - print(f"Unexpected error during initial page check: {e_main_check}") |
62 | | - os.makedirs("screenshots", exist_ok=True) |
63 | | - driver.save_screenshot(f"screenshots/error_initial_setup_main_check_exception_{int(time.time())}.png") |
64 | | - raise e_main_check |
| 42 | + current_url = self.driver.current_url |
| 43 | + logger.error(f"Failed to find grade input ('{self.GRADE_INPUT_SELECTOR}') on initial load. URL: {current_url}") |
| 44 | + self._take_screenshot("error_initial_setup_grade_input_not_found") |
| 45 | + # Ensure the exception message is clear |
| 46 | + raise Exception(f"Could not find the grade input ('{self.GRADE_INPUT_SELECTOR}') during setup. Current URL: {current_url}") |
| 47 | + |
| 48 | + def _add_grade_and_percentage(self, grade, percentage): |
| 49 | + # Ensure _initial_setup has been called or page is otherwise ready |
| 50 | + grade_input = self.wait_long.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.GRADE_INPUT_SELECTOR))) |
| 51 | + percentage_input = self.wait_long.until(EC.presence_of_element_located((By.CSS_SELECTOR, self.PERCENTAGE_INPUT_SELECTOR))) |
| 52 | + add_button = self.wait_long.until(EC.element_to_be_clickable((By.CSS_SELECTOR, self.ADD_GRADE_BUTTON_SELECTOR))) |
65 | 53 |
|
66 | | - def _add_grade_and_percentage(self, driver, grade, percentage): |
67 | | - grade_input = WebDriverWait(driver, 10).until( |
68 | | - EC.presence_of_element_located((By.ID, "grade-input")) |
69 | | - ) |
70 | 54 | grade_input.clear() |
71 | 55 | grade_input.send_keys(str(grade)) |
72 | | - |
73 | | - percentage_input = WebDriverWait(driver, 10).until( |
74 | | - EC.presence_of_element_located((By.ID, "percentage-input")) |
75 | | - ) |
76 | 56 | percentage_input.clear() |
77 | 57 | percentage_input.send_keys(str(percentage)) |
78 | | - |
79 | | - add_button = WebDriverWait(driver, 10).until( |
80 | | - EC.element_to_be_clickable((By.ID, "add-grade-btn")) |
81 | | - ) |
82 | 58 | add_button.click() |
| 59 | + logger.info(f"Added grade: {grade}, percentage: {percentage}") |
83 | 60 |
|
84 | | - def _get_grades_list_item_count(self, driver): |
| 61 | + def _get_grades_list_item_count(self): |
| 62 | + # This counts the number of displayed grade rows |
85 | 63 | try: |
86 | | - grades_list_container = driver.find_element(By.ID, "grades-list") |
87 | | - # Assuming direct children are the items; adjust selector if structure is different |
88 | | - return len(grades_list_container.find_elements(By.XPATH, "./*")) |
89 | | - except Exception: |
90 | | - return 0 # If list not found or empty |
| 64 | + grade_items = self.driver.find_elements(By.CSS_SELECTOR, self.GRADES_LIST_ITEM_SELECTOR) |
| 65 | + return len(grade_items) |
| 66 | + except Exception as e: |
| 67 | + logger.error(f"Error finding grade list items: {e}") |
| 68 | + self._take_screenshot("error_get_grades_list_item_count") |
| 69 | + return 0 |
91 | 70 |
|
| 71 | + # US01: Registro de Calificaciones |
92 | 72 | def test_us01_add_single_valid_grade(self, driver, request): # Added request fixture |
93 | 73 | test_name = request.node.name # Use request fixture to get test name |
94 | 74 | try: |
|
0 commit comments