459 lines
16 KiB
Python
Executable File
459 lines
16 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
End-to-End Script: Complete Profile to Assessment Ready State
|
|
|
|
This script performs the complete student journey:
|
|
1. Login (with smart password handling)
|
|
2. Password Reset (if needed)
|
|
3. Profile Completion (to 100%)
|
|
4. Navigate to Assessments Page
|
|
|
|
Usage:
|
|
python scripts/complete_profile_to_assessment.py --cpid <CPID> --password <PASSWORD> [--profile-data <JSON_FILE>]
|
|
|
|
Example:
|
|
python scripts/complete_profile_to_assessment.py --cpid BATBAT311A --password Admin@123
|
|
python scripts/complete_profile_to_assessment.py --cpid DESDES29BB --password Admin@123 --profile-data profile_data.json
|
|
"""
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
|
|
# Add project root to path
|
|
project_root = Path(__file__).parent.parent
|
|
sys.path.insert(0, str(project_root))
|
|
|
|
from pages.login_page import LoginPage
|
|
from pages.mandatory_reset_page import MandatoryResetPage
|
|
from pages.profile_incomplete_page import ProfileIncompletePage
|
|
from pages.profile_editor_page import ProfileEditorPage
|
|
from pages.dashboard_page import DashboardPage
|
|
from pages.assessments_page import AssessmentsPage
|
|
from utils.driver_manager import DriverManager
|
|
from utils.password_tracker import password_tracker
|
|
from config.config import TEST_NEW_PASSWORD, BASE_URL
|
|
|
|
|
|
def load_profile_data(json_file=None):
|
|
"""
|
|
Load profile data from JSON file or return default data
|
|
|
|
Args:
|
|
json_file: Path to JSON file with profile data (optional)
|
|
|
|
Returns:
|
|
dict: Profile data dictionary
|
|
"""
|
|
default_data = {
|
|
"personal_information": {
|
|
"first_name": "Test",
|
|
"last_name": "Student",
|
|
"gender": "Male",
|
|
"dob": "2005-01-15",
|
|
"roll_number": "12345",
|
|
"nationality": "Indian"
|
|
},
|
|
"contact_information": {
|
|
"email": "test.student@example.com",
|
|
"phone": "9876543210",
|
|
"address": "123 Test Street, Test Area",
|
|
"city": "Mumbai",
|
|
"state": "Maharashtra",
|
|
"zip_code": "400001",
|
|
"native_state": "Maharashtra"
|
|
},
|
|
"parent_guardian": {
|
|
"father_name": "Father Test",
|
|
"father_age_range": "41-50",
|
|
"father_occupation": "Engineer",
|
|
"father_email": "father@example.com",
|
|
"mother_name": "Mother Test",
|
|
"mother_age_range": "30-40",
|
|
"mother_occupation": "Teacher",
|
|
"mother_email": "mother@example.com"
|
|
},
|
|
"education_details": {
|
|
"full_name": "Test Student",
|
|
"current_grade": "10",
|
|
"section": "A",
|
|
"board_stream": "CBSE"
|
|
},
|
|
"focus_areas": {
|
|
"short_term": ["01. Academics", "02. Family", "03. Health"],
|
|
"long_term": ["01. Academics", "09. Future Aspiration", "06. Personal Growth"]
|
|
},
|
|
"self_assessment": {
|
|
"strengths": ["1. Quick Learning", "3. Problem-Solving", "12. Communication"],
|
|
"improvements": ["2. Curiosity", "6. Risk Taking", "10. Leadership"]
|
|
},
|
|
"hobbies_clubs": {
|
|
"hobbies": ["01. Reading", "03. Sports", "02. Playing Musical Instruments"],
|
|
"clubs": ["1. Science Club", "3. Quiz Club", "4. Literary Club"]
|
|
},
|
|
"achievements": {
|
|
"academics": "School topper in 9th grade",
|
|
"sports": "Won district level cricket tournament",
|
|
"cultural": "Participated in school annual day",
|
|
"others": "Volunteer work at local NGO"
|
|
},
|
|
"expectations": [
|
|
"1. Self-Understanding: Gain deeper insights into their personality, strengths, and areas for growth.",
|
|
"2. Career Guidance: Clear recommendations on suitable career paths or college majors based on their interests and abilities, backed by scientific tool.",
|
|
"3. Academic Support: Help in identifying their learning styles, study habits, or cognitive strengths to improve performance."
|
|
]
|
|
}
|
|
|
|
if json_file:
|
|
json_path = Path(json_file)
|
|
if json_path.exists():
|
|
with open(json_path, 'r') as f:
|
|
custom_data = json.load(f)
|
|
# Merge custom data with defaults (custom takes precedence)
|
|
merged_data = default_data.copy()
|
|
for key, value in custom_data.items():
|
|
if isinstance(value, dict) and key in merged_data:
|
|
merged_data[key].update(value)
|
|
else:
|
|
merged_data[key] = value
|
|
return merged_data
|
|
else:
|
|
print(f"⚠️ JSON file not found: {json_file}. Using default data.")
|
|
|
|
return default_data
|
|
|
|
|
|
def complete_profile_with_data(profile_editor, profile_data):
|
|
"""
|
|
Complete profile using provided data
|
|
|
|
Args:
|
|
profile_editor: ProfileEditorPage instance
|
|
profile_data: Dictionary with profile data
|
|
"""
|
|
print("\n🚀 Starting profile completion with provided data...")
|
|
|
|
# Step 1: Personal Information
|
|
print("\n📝 Step 1/9: Personal Information")
|
|
profile_editor.navigate_to_tab(0)
|
|
time.sleep(0.5)
|
|
personal = profile_data.get("personal_information", {})
|
|
profile_editor.fill_personal_information(
|
|
first_name=personal.get("first_name"),
|
|
last_name=personal.get("last_name"),
|
|
gender=personal.get("gender"),
|
|
dob=personal.get("dob"),
|
|
roll_number=personal.get("roll_number"),
|
|
nationality=personal.get("nationality")
|
|
)
|
|
print("✅ Personal Information filled")
|
|
|
|
# Step 2: Contact Information
|
|
print("\n📝 Step 2/9: Contact Information")
|
|
profile_editor.navigate_to_tab(1)
|
|
time.sleep(0.5)
|
|
contact = profile_data.get("contact_information", {})
|
|
profile_editor.fill_contact_information(
|
|
email=contact.get("email"),
|
|
phone=contact.get("phone"),
|
|
address=contact.get("address"),
|
|
city=contact.get("city"),
|
|
state=contact.get("state"),
|
|
zip_code=contact.get("zip_code"),
|
|
native_state=contact.get("native_state")
|
|
)
|
|
print("✅ Contact Information filled")
|
|
|
|
# Step 3: Parent/Guardian
|
|
print("\n📝 Step 3/9: Parent/Guardian")
|
|
profile_editor.navigate_to_tab(2)
|
|
time.sleep(0.5)
|
|
parent = profile_data.get("parent_guardian", {})
|
|
profile_editor.fill_parent_guardian(
|
|
father_name=parent.get("father_name"),
|
|
father_age_range=parent.get("father_age_range"),
|
|
father_occupation=parent.get("father_occupation"),
|
|
father_email=parent.get("father_email"),
|
|
mother_name=parent.get("mother_name"),
|
|
mother_age_range=parent.get("mother_age_range"),
|
|
mother_occupation=parent.get("mother_occupation"),
|
|
mother_email=parent.get("mother_email")
|
|
)
|
|
print("✅ Parent/Guardian filled")
|
|
|
|
# Step 4: Education Details
|
|
print("\n📝 Step 4/9: Education Details")
|
|
profile_editor.navigate_to_tab(3)
|
|
time.sleep(0.5)
|
|
education = profile_data.get("education_details", {})
|
|
profile_editor.fill_education_details(
|
|
full_name=education.get("full_name"),
|
|
current_grade=education.get("current_grade"),
|
|
section=education.get("section"),
|
|
board_stream=education.get("board_stream")
|
|
)
|
|
print("✅ Education Details filled")
|
|
|
|
# Step 5: Focus Areas
|
|
print("\n📝 Step 5/9: Focus Areas")
|
|
profile_editor.navigate_to_tab(4)
|
|
time.sleep(0.5)
|
|
focus = profile_data.get("focus_areas", {})
|
|
profile_editor.select_focus_areas(
|
|
short_term=focus.get("short_term"),
|
|
long_term=focus.get("long_term")
|
|
)
|
|
print("✅ Focus Areas selected")
|
|
|
|
# Step 6: Self-Assessment
|
|
print("\n📝 Step 6/9: Self-Assessment")
|
|
profile_editor.navigate_to_tab(5)
|
|
time.sleep(0.5)
|
|
assessment = profile_data.get("self_assessment", {})
|
|
profile_editor.select_strengths(assessment.get("strengths", []))
|
|
profile_editor.select_improvements(assessment.get("improvements", []))
|
|
print("✅ Self-Assessment completed")
|
|
|
|
# Step 7: Hobbies & Clubs
|
|
print("\n📝 Step 7/9: Hobbies & Clubs")
|
|
profile_editor.navigate_to_tab(6)
|
|
time.sleep(0.5)
|
|
hobbies_clubs = profile_data.get("hobbies_clubs", {})
|
|
profile_editor.select_hobbies(hobbies_clubs.get("hobbies", []))
|
|
profile_editor.select_clubs(hobbies_clubs.get("clubs", []))
|
|
print("✅ Hobbies & Clubs selected")
|
|
|
|
# Step 8: Achievements
|
|
print("\n📝 Step 8/9: Achievements")
|
|
profile_editor.navigate_to_tab(7)
|
|
time.sleep(0.5)
|
|
achievements = profile_data.get("achievements", {})
|
|
profile_editor.fill_achievements(
|
|
academics=achievements.get("academics"),
|
|
sports=achievements.get("sports"),
|
|
cultural=achievements.get("cultural"),
|
|
others=achievements.get("others")
|
|
)
|
|
print("✅ Achievements filled")
|
|
|
|
# Step 9: Expectations
|
|
print("\n📝 Step 9/9: Expectations")
|
|
profile_editor.navigate_to_tab(8)
|
|
time.sleep(0.5)
|
|
expectations = profile_data.get("expectations", [])
|
|
profile_editor.select_expectations(expectations)
|
|
print("✅ Expectations selected")
|
|
|
|
# Save profile
|
|
print("\n💾 Saving profile...")
|
|
progress_before = profile_editor.get_progress_value()
|
|
print(f"📊 Progress before save: {progress_before}")
|
|
|
|
profile_editor.click_save()
|
|
time.sleep(2)
|
|
|
|
progress_after = profile_editor.get_progress_value()
|
|
print(f"📊 Progress after save: {progress_after}")
|
|
|
|
if "100%" in progress_after or progress_after == "100":
|
|
print("✅ Profile completed to 100%!")
|
|
return True
|
|
else:
|
|
print(f"⚠️ Profile not at 100% yet. Current: {progress_after}")
|
|
# Try saving again
|
|
profile_editor.click_save()
|
|
time.sleep(2)
|
|
progress_final = profile_editor.get_progress_value()
|
|
print(f"📊 Final progress: {progress_final}")
|
|
return "100%" in progress_final or progress_final == "100"
|
|
|
|
|
|
def main():
|
|
"""Main execution function"""
|
|
parser = argparse.ArgumentParser(
|
|
description="Complete student profile to 100% and navigate to assessments",
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="""
|
|
Examples:
|
|
# Basic usage with default data
|
|
python scripts/complete_profile_to_assessment.py --cpid BATBAT311A --password Admin@123
|
|
|
|
# With custom profile data
|
|
python scripts/complete_profile_to_assessment.py --cpid DESDES29BB --password Admin@123 --profile-data profile_data.json
|
|
"""
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--cpid",
|
|
required=True,
|
|
help="Student CPID (e.g., BATBAT311A)"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--password",
|
|
required=True,
|
|
help="Student password (will try this first, then Admin@123 if needed)"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--profile-data",
|
|
help="Path to JSON file with custom profile data (optional)"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--headless",
|
|
action="store_true",
|
|
help="Run in headless mode (no browser window)"
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Load profile data
|
|
profile_data = load_profile_data(args.profile_data)
|
|
|
|
# Initialize driver
|
|
driver = None
|
|
try:
|
|
print("=" * 80)
|
|
print("🚀 COMPLETE PROFILE TO ASSESSMENT - END-TO-END SCRIPT")
|
|
print("=" * 80)
|
|
print(f"\n📋 Configuration:")
|
|
print(f" CPID: {args.cpid}")
|
|
print(f" Password: {'*' * len(args.password)}")
|
|
print(f" Profile Data: {'Custom' if args.profile_data else 'Default'}")
|
|
print(f" Headless: {args.headless}")
|
|
print(f" Base URL: {BASE_URL}")
|
|
print()
|
|
|
|
# Get driver
|
|
driver = DriverManager.get_driver(headless=args.headless)
|
|
|
|
# Step 1: Login
|
|
print("\n" + "=" * 80)
|
|
print("STEP 1: LOGIN")
|
|
print("=" * 80)
|
|
login_page = LoginPage(driver)
|
|
login_page.login(identifier=args.cpid, password=args.password)
|
|
print(f"✅ Login successful for {args.cpid}")
|
|
|
|
# Step 2: Handle Password Reset (if needed)
|
|
print("\n" + "=" * 80)
|
|
print("STEP 2: PASSWORD RESET (if needed)")
|
|
print("=" * 80)
|
|
reset_page = MandatoryResetPage(driver)
|
|
if reset_page.is_modal_present():
|
|
print("🔐 Password reset modal detected - resetting password...")
|
|
current_password = password_tracker.get_password(args.cpid, args.password)
|
|
reset_page.reset_password(
|
|
current_password=current_password,
|
|
new_password=TEST_NEW_PASSWORD,
|
|
confirm_password=TEST_NEW_PASSWORD,
|
|
student_cpid=args.cpid
|
|
)
|
|
print(f"✅ Password reset to {TEST_NEW_PASSWORD}")
|
|
else:
|
|
print("✅ No password reset needed")
|
|
|
|
# Step 3: Handle Profile Incomplete Modal (if needed)
|
|
print("\n" + "=" * 80)
|
|
print("STEP 3: PROFILE INCOMPLETE MODAL (if needed)")
|
|
print("=" * 80)
|
|
profile_incomplete = ProfileIncompletePage(driver)
|
|
if profile_incomplete.is_modal_present():
|
|
progress = profile_incomplete.get_progress_value()
|
|
print(f"📊 Current profile progress: {progress}")
|
|
print("📝 Clicking 'Complete Profile Now' button...")
|
|
profile_incomplete.click_complete()
|
|
print("✅ Navigated to profile editor")
|
|
else:
|
|
print("✅ Profile incomplete modal not present")
|
|
|
|
# Step 4: Complete Profile to 100%
|
|
print("\n" + "=" * 80)
|
|
print("STEP 4: COMPLETE PROFILE TO 100%")
|
|
print("=" * 80)
|
|
profile_editor = ProfileEditorPage(driver)
|
|
profile_editor.wait_for_page_load()
|
|
|
|
initial_progress = profile_editor.get_progress_value()
|
|
print(f"📊 Initial profile progress: {initial_progress}")
|
|
|
|
if "100%" in initial_progress or initial_progress == "100":
|
|
print("✅ Profile is already 100% complete!")
|
|
else:
|
|
# Complete profile with provided data
|
|
success = complete_profile_with_data(profile_editor, profile_data)
|
|
if not success:
|
|
print("❌ Failed to complete profile to 100%")
|
|
return 1
|
|
|
|
# Step 5: Navigate to Assessments
|
|
print("\n" + "=" * 80)
|
|
print("STEP 5: NAVIGATE TO ASSESSMENTS")
|
|
print("=" * 80)
|
|
|
|
# Navigate to dashboard first
|
|
dashboard = DashboardPage(driver)
|
|
dashboard.navigate()
|
|
time.sleep(1)
|
|
|
|
# Click Assessments link
|
|
dashboard.click_assessments()
|
|
time.sleep(2)
|
|
|
|
# Verify we're on assessments page
|
|
assessments = AssessmentsPage(driver)
|
|
assessments.wait_for_page_load()
|
|
|
|
current_url = driver.current_url
|
|
if "/assessments" in current_url:
|
|
print("✅ Successfully navigated to Assessments page!")
|
|
print(f" URL: {current_url}")
|
|
else:
|
|
print(f"⚠️ Unexpected URL: {current_url}")
|
|
|
|
# Final summary
|
|
print("\n" + "=" * 80)
|
|
print("✅ SUCCESS - STUDENT IS NOW ASSESSMENT READY!")
|
|
print("=" * 80)
|
|
print(f"\n📋 Summary:")
|
|
print(f" CPID: {args.cpid}")
|
|
print(f" Profile Status: 100% Complete")
|
|
print(f" Current Page: Assessments")
|
|
print(f" URL: {driver.current_url}")
|
|
print("\n🎉 Student can now access and take assessments!")
|
|
|
|
# Keep browser open for inspection (if not headless)
|
|
if not args.headless:
|
|
print("\n⏸️ Browser will remain open for 30 seconds for inspection...")
|
|
print(" Press Ctrl+C to close immediately")
|
|
try:
|
|
time.sleep(30)
|
|
except KeyboardInterrupt:
|
|
print("\n👋 Closing browser...")
|
|
|
|
return 0
|
|
|
|
except Exception as e:
|
|
print(f"\n❌ ERROR: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return 1
|
|
|
|
finally:
|
|
if driver:
|
|
driver.quit()
|
|
print("\n👋 Browser closed")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|
|
|
|
|
|
|
|
|
|
|
|
|