278 lines
12 KiB
Python
278 lines
12 KiB
Python
"""
|
|
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
|
|
|