""" Age Verification Modal Page Object Model Handles the age verification modal that appears when DOB doesn't match school records. Scope: age_verification """ from selenium.webdriver.common.by import By from pages.base_page import BasePage class AgeVerificationModal(BasePage): """Page Object for Age Verification Modal""" # Locators - Need to verify with actual DOM MODAL = (By.CSS_SELECTOR, "[data-testid='age_verification__modal']") TITLE = (By.CSS_SELECTOR, "[data-testid='age_verification__title']") WARNING_BANNER = (By.CSS_SELECTOR, "[data-testid='age_verification__warning_banner']") VERIFIED_AGE = (By.CSS_SELECTOR, "[data-testid='age_verification__verified_age']") NEW_AGE = (By.CSS_SELECTOR, "[data-testid='age_verification__new_age']") DIFFERENCE = (By.CSS_SELECTOR, "[data-testid='age_verification__difference']") CONFIRM_CHECKBOX = (By.CSS_SELECTOR, "[data-testid='age_verification__confirm_checkbox']") CANCEL_BUTTON = (By.CSS_SELECTOR, "[data-testid='age_verification__cancel_button']") CONFIRM_BUTTON = (By.CSS_SELECTOR, "[data-testid='age_verification__confirm_button']") CLOSE_BUTTON = (By.CSS_SELECTOR, "[data-testid='age_verification__close_button']") def __init__(self, driver): """Initialize Age Verification Modal""" super().__init__(driver) def is_modal_present(self): """ Check if age verification modal is present. Uses multiple detection strategies: 1. Check for modal by data-testid 2. Check for modal by title text "Age Verification Required" 3. Check for modal overlay structure """ from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from config.config import SHORT_WAIT # Strategy 1: Check by data-testid try: if self.is_element_visible(self.MODAL, timeout=2): return True except: pass # Strategy 2: Check for title text try: title_elements = self.driver.find_elements(By.XPATH, "//*[contains(text(), 'Age Verification Required') or contains(text(), 'Age Verification')]") if title_elements: # Check if it's in a modal structure for element in title_elements: # Check if parent is a modal (has overlay or modal classes) parent = self.driver.execute_script("return arguments[0].closest('[class*=\"modal\"], [class*=\"overlay\"], [role=\"dialog\"]');", element) if parent: return True except: pass # Strategy 3: Check page source for age verification text try: page_text = self.driver.page_source.lower() if "age verification required" in page_text or "date of birth verification" in page_text: # Check if modal overlay is visible overlays = self.driver.find_elements(By.CSS_SELECTOR, "div[class*='fixed'][class*='inset-0'][class*='bg-black']") for overlay in overlays: if overlay.is_displayed(): return True except: pass return False def get_verified_age(self): """Get verified age from school records""" try: # Try to find verified age text elements = self.driver.find_elements(By.XPATH, "//*[contains(text(), 'Verified Age') or contains(text(), 'from school')]") for element in elements: text = element.text # Extract age number import re numbers = re.findall(r'\d+', text) if numbers: return int(numbers[0]) except: pass return None def get_new_age(self): """Get new age from entered DOB""" try: # Try to find new age text elements = self.driver.find_elements(By.XPATH, "//*[contains(text(), 'New Age') or contains(text(), 'from your DOB')]") for element in elements: text = element.text # Extract age number import re numbers = re.findall(r'\d+', text) if numbers: return int(numbers[1]) if len(numbers) > 1 else int(numbers[0]) except: pass return None def confirm_age(self): """ Confirm age verification by checking checkbox and clicking OK. This handles the age verification modal that appears when DOB doesn't match. """ import time from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from config.config import SHORT_WAIT if not self.is_modal_present(): print("✅ Age verification modal not present - no action needed") return True print("🔍 Age verification modal detected - handling...") # Wait for modal to be fully visible time.sleep(1) # Strategy 1: Try to find confirm checkbox by ID (most reliable) # The checkbox has id="age-confirmation-checkbox" in the UI code checkbox_found = False try: checkbox = WebDriverWait(self.driver, SHORT_WAIT).until( EC.presence_of_element_located((By.ID, "age-confirmation-checkbox")) ) if not checkbox.is_selected(): # Scroll into view self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", checkbox) time.sleep(0.3) # Try regular click first try: checkbox.click() print("✅ Age confirmation checkbox checked (by ID)") checkbox_found = True except: # Fallback to JavaScript click self.driver.execute_script("arguments[0].click();", checkbox) print("✅ Age confirmation checkbox checked (by ID, JavaScript click)") checkbox_found = True except Exception as e: print(f"⚠️ Could not find checkbox by ID: {e}") # Strategy 2: Try to find by label text if ID failed if not checkbox_found: try: # Find checkbox with label containing "I confirm that the date of birth" checkbox_xpath = ( "//label[contains(text(), 'I confirm that the date of birth')]//input[@type='checkbox'] | " "//input[@type='checkbox'][following-sibling::label[contains(text(), 'I confirm that the date of birth')]]" ) checkbox = WebDriverWait(self.driver, SHORT_WAIT).until( EC.presence_of_element_located((By.XPATH, checkbox_xpath)) ) if not checkbox.is_selected(): self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", checkbox) time.sleep(0.3) self.driver.execute_script("arguments[0].click();", checkbox) print("✅ Age confirmation checkbox checked (by label text)") checkbox_found = True except Exception as e: print(f"⚠️ Could not find checkbox by label: {e}") # Strategy 3: Find any checkbox in modal (fallback) if not checkbox_found: try: # Find modal container first modal = self.driver.find_element(By.XPATH, "//*[contains(text(), 'Age Verification Required')]/ancestor::div[contains(@class, 'bg-white') or contains(@class, 'rounded-2xl')]") checkbox = modal.find_element(By.XPATH, ".//input[@type='checkbox']") if not checkbox.is_selected(): self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", checkbox) time.sleep(0.3) self.driver.execute_script("arguments[0].click();", checkbox) print("✅ Age confirmation checkbox checked (fallback)") checkbox_found = True except Exception as e: print(f"⚠️ Could not find checkbox in modal: {e}") if not checkbox_found: print("⚠️ Warning: Could not find/check confirmation checkbox - button may be disabled") # Click OK/Confirm button # The button text is "OK - Confirm Update" try: # Find button with text "OK", "Confirm", or "OK - Confirm Update" confirm_button_xpath = ( "//button[contains(text(), 'OK - Confirm Update')] | " "//button[contains(text(), 'OK') and contains(text(), 'Confirm')] | " "//button[contains(text(), 'Confirm Update')]" ) confirm_button = WebDriverWait(self.driver, SHORT_WAIT).until( EC.element_to_be_clickable((By.XPATH, confirm_button_xpath)) ) # Scroll into view self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", confirm_button) time.sleep(0.3) # Try regular click first try: confirm_button.click() print("✅ Age verification confirmed - clicked OK button") except: # Fallback to JavaScript click self.driver.execute_script("arguments[0].click();", confirm_button) print("✅ Age verification confirmed (JavaScript click)") except Exception as e: print(f"⚠️ Could not find confirm button by text: {e}") # Try alternative: find by data-testid try: confirm_button = self.wait.wait_for_element_clickable(self.CONFIRM_BUTTON, timeout=2) confirm_button.click() print("✅ Age verification confirmed (by data-testid)") except: # Try JavaScript click on any button in modal try: # Find modal container first modal = self.driver.find_element(By.XPATH, "//*[contains(text(), 'Age Verification Required')]/ancestor::div[contains(@class, 'bg-white') or contains(@class, 'modal')]") buttons = modal.find_elements(By.XPATH, ".//button[contains(text(), 'OK') or contains(text(), 'Confirm')]") for button in buttons: if button.is_displayed() and "Cancel" not in button.text: self.driver.execute_script("arguments[0].click();", button) print("✅ Age verification confirmed (fallback JavaScript click)") break except Exception as e2: print(f"⚠️ Could not click confirm button: {e2}") raise Exception(f"Failed to confirm age verification: {e}, {e2}") # Wait for modal to close time.sleep(2) # Verify modal is closed if not self.is_modal_present(): print("✅ Age verification modal closed successfully") return True else: print("⚠️ Age verification modal still present after confirmation") return False def cancel_age_verification(self): """Cancel age verification (closes modal without confirming)""" import time from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from config.config import SHORT_WAIT if not self.is_modal_present(): return True try: # Find Cancel button cancel_button = WebDriverWait(self.driver, SHORT_WAIT).until( EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Cancel')]")) ) cancel_button.click() time.sleep(1) print("✅ Age verification cancelled") return True except: return False