CP_AUTOMATION/scripts/verify_ui_team_implementation.py
2025-12-12 19:54:54 +05:30

357 lines
16 KiB
Python

"""
Verify UI Team's Implementation of Missing Attributes
This script verifies that all 5 missing attributes are actually present in the DOM
after the UI team's implementation.
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from pages.login_page import LoginPage
from pages.profile_editor_page import ProfileEditorPage
from pages.domain_assessment_page import DomainAssessmentPage
from pages.assessments_page import AssessmentsPage
from pages.domains_page import DomainsPage
from utils.password_tracker import password_tracker
from config.config import TEST_USERNAME, TEST_NEW_PASSWORD, BASE_URL
import time
def verify_toast_attribute(driver, test_id, description):
"""Verify toast attribute is present in DOM"""
print(f"\n🔍 Verifying: {description}")
print(f" Looking for: [data-testid='{test_id}']")
try:
# Wait for toast to appear and data-testid to be added (UI team's helper takes max 1 second)
# Check multiple times as toast helpers add attribute programmatically
max_attempts = 10
for attempt in range(max_attempts):
time.sleep(0.3) # Wait a bit for attribute to be added
# Check if attribute exists in DOM
elements = driver.find_elements(By.CSS_SELECTOR, f"[data-testid='{test_id}']")
if elements:
visible_elements = [e for e in elements if e.is_displayed()]
if visible_elements:
print(f" ✅ FOUND: {len(visible_elements)} visible element(s) (attempt {attempt + 1})")
# Also check if it has role="status" (should have both)
for elem in visible_elements:
role = elem.get_attribute("role")
if role == "status":
print(f" ✅ Also has role='status' (correct)")
return True
else:
if attempt < max_attempts - 1:
continue # Retry
print(f" ⚠️ Found but not visible: {len(elements)} element(s)")
return False
# Also check page source as fallback
if attempt == max_attempts - 1:
page_source = driver.page_source
if test_id in page_source:
print(f" ⚠️ Found in page source but not as DOM element")
return False
print(f" ❌ NOT FOUND in DOM after {max_attempts} attempts")
return False
except Exception as e:
print(f" ❌ ERROR: {e}")
return False
def verify_static_attribute(driver, test_id, description):
"""Verify static attribute is present in DOM"""
print(f"\n🔍 Verifying: {description}")
print(f" Looking for: [data-testid='{test_id}']")
try:
element = WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.CSS_SELECTOR, f"[data-testid='{test_id}']"))
)
if element.is_displayed():
print(f" ✅ FOUND and VISIBLE")
return True
else:
print(f" ⚠️ Found but not visible")
return False
except Exception as e:
print(f" ❌ NOT FOUND: {e}")
return False
def main():
print("=" * 70)
print("UI TEAM IMPLEMENTATION VERIFICATION")
print("=" * 70)
options = Options()
options.add_argument('--headless=new')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(5)
results = {}
try:
# 1. Verify Login Error (Banner and Toast)
print("\n" + "=" * 70)
print("1. LOGIN ERROR (BANNER AND TOAST)")
print("=" * 70)
login_page = LoginPage(driver)
login_page.navigate()
# Try invalid login to trigger error
login_page.send_keys(login_page.IDENTIFIER_INPUT, "INVALID_USER_12345")
login_page.send_keys(login_page.PASSWORD_INPUT, "INVALID_PASS_12345")
time.sleep(3) # Allow UI to stabilize
# Use JavaScript click to avoid interception
try:
submit_button = WebDriverWait(driver, 5).until(
EC.element_to_be_clickable(login_page.SUBMIT_BUTTON)
)
driver.execute_script("arguments[0].click();", submit_button)
except Exception as e:
print(f" ⚠️ Error clicking submit button: {e}")
# Try alternative: find and click via JavaScript
submit_button = driver.find_element(*login_page.SUBMIT_BUTTON)
driver.execute_script("arguments[0].click();", submit_button)
time.sleep(5) # Wait for error to appear
# Check for error banner (inline error - this is what actually appears)
print("\n Checking for Error Banner (inline error):")
results['login_error_banner'] = verify_static_attribute(
driver,
'student_login__error_banner',
'Login Error Banner (Inline)'
)
# Check for error toast (toast notification - may not appear)
print("\n Checking for Error Toast (toast notification):")
results['login_error_toast'] = verify_toast_attribute(
driver,
'student_login__error_toast',
'Login Error Toast'
)
# Document finding
if results['login_error_banner'] and not results['login_error_toast']:
print("\n 📝 NOTE: Login error is displayed as inline banner, not toast.")
print(" ✅ Automation uses error banner (student_login__error_banner) - WORKING")
print(" ⚠️ Toast (student_login__error_toast) not appearing - may be UI team issue")
# 2. Verify Profile Editor Toasts (requires login and navigation)
print("\n" + "=" * 70)
print("2. PROFILE EDITOR TOASTS")
print("=" * 70)
# Login with valid credentials
driver.get(BASE_URL)
time.sleep(2)
# Use JavaScript click for login to avoid interception
try:
login_page.send_keys(login_page.IDENTIFIER_INPUT, TEST_USERNAME)
login_page.send_keys(login_page.PASSWORD_INPUT, TEST_NEW_PASSWORD)
time.sleep(2)
submit_button = WebDriverWait(driver, 5).until(
EC.element_to_be_clickable(login_page.SUBMIT_BUTTON)
)
driver.execute_script("arguments[0].click();", submit_button)
time.sleep(5) # Wait for login to complete
except Exception as e:
print(f" ⚠️ Error during login: {e}")
# Fallback: try regular login method
login_page.login(TEST_USERNAME, TEST_NEW_PASSWORD)
time.sleep(3)
# Navigate to profile editor
profile_editor = ProfileEditorPage(driver)
profile_editor.navigate()
profile_editor.wait_for_page_load()
time.sleep(2)
# Check if profile editor page is loaded
if profile_editor.is_element_visible(profile_editor.PAGE, timeout=5):
print(" ✅ Profile editor page loaded")
print(" Note: Profile editor toasts require actual save operation")
print(" Checking if toast locators are defined correctly...")
# Verify locators are defined (code-level check)
if hasattr(profile_editor, 'SUCCESS_TOAST') and hasattr(profile_editor, 'ERROR_TOAST'):
print(f" ✅ SUCCESS_TOAST locator defined: {profile_editor.SUCCESS_TOAST}")
print(f" ✅ ERROR_TOAST locator defined: {profile_editor.ERROR_TOAST}")
results['profile_editor_success_toast'] = "LOCATOR_DEFINED"
results['profile_editor_error_toast'] = "LOCATOR_DEFINED"
else:
print(" ❌ Toast locators not defined in page object")
results['profile_editor_success_toast'] = False
results['profile_editor_error_toast'] = False
else:
print(" ❌ Profile editor page not loaded")
results['profile_editor_success_toast'] = False
results['profile_editor_error_toast'] = False
# 3. Verify Assessment Header Product Name
print("\n" + "=" * 70)
print("3. ASSESSMENT HEADER - PRODUCT NAME")
print("=" * 70)
# Navigate to assessments
assessments_page = AssessmentsPage(driver)
assessments_page.navigate()
assessments_page.wait_for_page_load()
time.sleep(2)
# Get first assessment and start it
assessment_ids = assessments_page.get_assessment_ids()
if assessment_ids:
# Use JavaScript click to avoid interception
try:
assessment_card = driver.find_element(
By.CSS_SELECTOR,
f"[data-testid='assessment_card__{assessment_ids[0]}_action']"
)
driver.execute_script("arguments[0].click();", assessment_card)
except Exception as e:
print(f" ⚠️ Error clicking assessment: {e}")
assessments_page.click_begin_assessment(assessment_ids[0])
time.sleep(3)
# Navigate to first domain
domains_page = DomainsPage(driver)
domains_page.wait_for_page_load()
time.sleep(2)
domain_ids = domains_page.get_all_domain_ids()
unlocked_domain_id = None
for domain_id in domain_ids:
if domains_page.is_domain_unlocked(domain_id):
unlocked_domain_id = domain_id
break
if unlocked_domain_id:
# Use JavaScript click to avoid interception
try:
domain_card = driver.find_element(
By.CSS_SELECTOR,
f"[data-testid='domain_card__{unlocked_domain_id}_action']"
)
driver.execute_script("arguments[0].click();", domain_card)
except Exception as e:
print(f" ⚠️ Error clicking domain: {e}")
domains_page.click_start_domain(unlocked_domain_id)
time.sleep(5)
# Dismiss instructions modal if present
domain_assessment = DomainAssessmentPage(driver)
if domain_assessment.is_instructions_modal_present():
domain_assessment.dismiss_instructions_modal()
time.sleep(2)
results['assessment_header_product_name'] = verify_static_attribute(
driver,
'domain_assessment__header__product_name',
'Assessment Header Product Name'
)
# 4. Verify Question Counter
print("\n" + "=" * 70)
print("4. ACTION BAR - QUESTION COUNTER")
print("=" * 70)
results['question_counter'] = verify_static_attribute(
driver,
'domain_assessment__action_bar__question_counter',
'Question Counter in Action Bar'
)
else:
print(" ⚠️ No unlocked domain found")
results['assessment_header_product_name'] = False
results['question_counter'] = False
else:
print(" ⚠️ No assessments found")
results['assessment_header_product_name'] = False
results['question_counter'] = False
except Exception as e:
print(f"\n❌ ERROR during verification: {e}")
import traceback
traceback.print_exc()
finally:
driver.quit()
# Print Summary
print("\n" + "=" * 70)
print("VERIFICATION SUMMARY")
print("=" * 70)
summary = {
'High Priority': {
'student_login__error_banner': results.get('login_error_banner', False),
'student_login__error_toast': results.get('login_error_toast', False),
'profile_editor__success_toast': results.get('profile_editor_success_toast', False),
'profile_editor__error_toast': results.get('profile_editor_error_toast', False),
},
'Medium Priority': {
'domain_assessment__header__product_name': results.get('assessment_header_product_name', False),
'domain_assessment__action_bar__question_counter': results.get('question_counter', False),
}
}
for priority, attrs in summary.items():
print(f"\n{priority}:")
for attr, result in attrs.items():
if result == True:
print(f"{attr}")
elif result == "LOCATOR_DEFINED":
print(f" ⚠️ {attr} - Locator defined (needs actual toast to verify)")
elif result == "NEEDS_MANUAL_TEST":
print(f" ⚠️ {attr} - Needs manual test (requires user action)")
else:
print(f"{attr}")
# Calculate completion
# Note: student_login__error_banner is the actual working locator (inline error)
# student_login__error_toast is the toast (may not appear for this error type)
high_priority_verified = sum(1 for v in summary['High Priority'].values() if v == True)
high_priority_defined = sum(1 for v in summary['High Priority'].values() if v == "LOCATOR_DEFINED")
medium_priority_verified = sum(1 for v in summary['Medium Priority'].values() if v == True)
# Critical attributes (what automation actually uses)
critical_verified = sum(1 for k, v in summary['High Priority'].items()
if k in ['student_login__error_banner', 'profile_editor__success_toast', 'profile_editor__error_toast']
and v == True)
print(f"\n📊 Completion:")
print(f" Critical (for automation): {critical_verified}/3 verified")
print(f" High Priority: {high_priority_verified}/4 verified, {high_priority_defined}/4 locators defined")
print(f" Medium Priority: {medium_priority_verified}/2 verified")
print(f" Total Verified: {high_priority_verified + medium_priority_verified}/6")
print(f" Total (with locators): {high_priority_verified + high_priority_defined + medium_priority_verified}/6")
print(f"\n📝 Notes:")
print(f" - student_login__error_banner: Inline error (actually used by automation) ✅")
print(f" - student_login__error_toast: Toast notification (may not appear for 'User not found' error)")
print(f" - Profile editor toasts: Need actual save/error operation to verify")
if critical_verified == 3 and medium_priority_verified == 2:
print("\n✅ ALL CRITICAL ATTRIBUTES VERIFIED - 100% READY FOR AUTOMATION!")
elif high_priority_verified >= 3 and medium_priority_verified == 2:
print("\n✅ ALL REQUIRED ATTRIBUTES IMPLEMENTED - 100% COMPLETE!")
print("⚠️ Some toast attributes need actual operations to verify")
else:
print("\n⚠️ Some attributes need verification")
if __name__ == "__main__":
main()