2026.03.29 20:00 Gitea_manager javítás előtt
This commit is contained in:
282
backend/tests/e2e_smoke_test.py
Normal file
282
backend/tests/e2e_smoke_test.py
Normal file
@@ -0,0 +1,282 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
E2E Smoke Test for Registration Flow
|
||||
Performs a complete "Blind Test" of the registration-to-activation flow.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import uuid
|
||||
import httpx
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any, Optional
|
||||
import sys
|
||||
|
||||
# Configuration
|
||||
API_BASE_URL = "http://sf_api:8000/api/v1"
|
||||
MAILPIT_API = "http://sf_mailpit:8025/api/v1"
|
||||
|
||||
def generate_unique_email() -> str:
|
||||
"""Generate a unique email for testing."""
|
||||
timestamp = int(time.time())
|
||||
random_id = uuid.uuid4().hex[:8]
|
||||
return f"test_{timestamp}_{random_id}@example.com"
|
||||
|
||||
async def call_registration(email: str) -> Dict[str, Any]:
|
||||
"""Call the registration API endpoint."""
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
payload = {
|
||||
"email": email,
|
||||
"password": "TestPassword123!",
|
||||
"first_name": "Test",
|
||||
"last_name": "User",
|
||||
"region_code": "HU",
|
||||
"lang": "hu"
|
||||
}
|
||||
|
||||
print(f"📝 Registering user with email: {email}")
|
||||
response = await client.post(f"{API_BASE_URL}/auth/register", json=payload)
|
||||
|
||||
if response.status_code != 201:
|
||||
print(f"❌ Registration failed: {response.status_code}")
|
||||
print(f"Response: {response.text}")
|
||||
return {"success": False, "error": f"HTTP {response.status_code}"}
|
||||
|
||||
data = response.json()
|
||||
print(f"✅ Registration successful: {data.get('message')}")
|
||||
print(f" User ID: {data.get('user_id')}")
|
||||
return {"success": True, "data": data}
|
||||
|
||||
async def get_verification_token_from_db(email: str) -> Optional[str]:
|
||||
"""Get verification token directly from the database."""
|
||||
import os
|
||||
import asyncpg
|
||||
|
||||
# Database connection parameters from environment
|
||||
db_host = os.getenv("DB_HOST", "shared-postgres")
|
||||
db_name = os.getenv("DB_NAME", "service_finder")
|
||||
db_user = os.getenv("DB_USER", "service_finder_app")
|
||||
db_password = os.getenv("DB_PASSWORD", "JELSZAVAD")
|
||||
|
||||
try:
|
||||
# Connect to database
|
||||
conn = await asyncpg.connect(
|
||||
host=db_host,
|
||||
database=db_name,
|
||||
user=db_user,
|
||||
password=db_password
|
||||
)
|
||||
|
||||
# Get user ID from email
|
||||
user_row = await conn.fetchrow(
|
||||
"SELECT id FROM identity.users WHERE email = $1",
|
||||
email
|
||||
)
|
||||
|
||||
if not user_row:
|
||||
print(f"❌ User not found in database for email: {email}")
|
||||
return None
|
||||
|
||||
user_id = user_row['id']
|
||||
|
||||
# Get verification token
|
||||
token_row = await conn.fetchrow(
|
||||
"""SELECT token FROM identity.verification_tokens
|
||||
WHERE user_id = $1 AND token_type = 'registration'
|
||||
ORDER BY created_at DESC LIMIT 1""",
|
||||
user_id
|
||||
)
|
||||
|
||||
await conn.close()
|
||||
|
||||
if token_row:
|
||||
token = str(token_row['token'])
|
||||
print(f"🔑 Found verification token in DB: {token[:8]}...")
|
||||
return token
|
||||
else:
|
||||
print("❌ No verification token found in database")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Database error: {e}")
|
||||
return None
|
||||
|
||||
async def get_verification_token_from_mailpit(email: str) -> Optional[str]:
|
||||
"""Try to get verification token from Mailpit API."""
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
# Get latest messages
|
||||
response = await client.get(f"{MAILPIT_API}/messages")
|
||||
if response.status_code != 200:
|
||||
print(f"❌ Mailpit API error: {response.status_code}")
|
||||
return None
|
||||
|
||||
messages = response.json().get('messages', [])
|
||||
|
||||
# Find message sent to our test email
|
||||
for msg in messages:
|
||||
if msg.get('To', [{}])[0].get('Address') == email:
|
||||
msg_id = msg['ID']
|
||||
# Get message details
|
||||
msg_response = await client.get(f"{MAILPIT_API}/message/{msg_id}")
|
||||
if msg_response.status_code == 200:
|
||||
msg_data = msg_response.json()
|
||||
html = msg_data.get('HTML', '')
|
||||
|
||||
# Extract token from HTML (look for token= parameter)
|
||||
import re
|
||||
token_match = re.search(r'token=([a-f0-9\-]+)', html)
|
||||
if token_match:
|
||||
token = token_match.group(1)
|
||||
print(f"📧 Found verification token in email: {token[:8]}...")
|
||||
return token
|
||||
|
||||
# Also check text body
|
||||
text = msg_data.get('Text', '')
|
||||
token_match = re.search(r'token=([a-f0-9\-]+)', text)
|
||||
if token_match:
|
||||
token = token_match.group(1)
|
||||
print(f"📧 Found verification token in email text: {token[:8]}...")
|
||||
return token
|
||||
|
||||
print("❌ No email found in Mailpit for the test address")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Mailpit error: {e}")
|
||||
return None
|
||||
|
||||
async def verify_email(token: str) -> bool:
|
||||
"""Call the verify-email endpoint."""
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
payload = {"token": token}
|
||||
|
||||
print(f"🔐 Verifying email with token: {token[:8]}...")
|
||||
response = await client.post(f"{API_BASE_URL}/auth/verify-email", json=payload)
|
||||
|
||||
if response.status_code != 200:
|
||||
print(f"❌ Email verification failed: {response.status_code}")
|
||||
print(f"Response: {response.text}")
|
||||
return False
|
||||
|
||||
data = response.json()
|
||||
print(f"✅ Email verification successful: {data.get('message')}")
|
||||
return True
|
||||
|
||||
async def check_user_activated(email: str) -> bool:
|
||||
"""Check if user is activated in database."""
|
||||
import os
|
||||
import asyncpg
|
||||
|
||||
db_host = os.getenv("DB_HOST", "shared-postgres")
|
||||
db_name = os.getenv("DB_NAME", "service_finder")
|
||||
db_user = os.getenv("DB_USER", "service_finder_app")
|
||||
db_password = os.getenv("DB_PASSWORD", "JELSZAVAD")
|
||||
|
||||
try:
|
||||
conn = await asyncpg.connect(
|
||||
host=db_host,
|
||||
database=db_name,
|
||||
user=db_user,
|
||||
password=db_password
|
||||
)
|
||||
|
||||
user_row = await conn.fetchrow(
|
||||
"SELECT is_active FROM identity.users WHERE email = $1",
|
||||
email
|
||||
)
|
||||
|
||||
await conn.close()
|
||||
|
||||
if user_row:
|
||||
is_active = user_row['is_active']
|
||||
print(f"👤 User activation status: {'ACTIVE' if is_active else 'INACTIVE'}")
|
||||
return is_active
|
||||
else:
|
||||
print("❌ User not found when checking activation")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Database error checking activation: {e}")
|
||||
return False
|
||||
|
||||
async def main():
|
||||
"""Main test execution."""
|
||||
print("=" * 60)
|
||||
print("🚀 Service Finder Registration E2E Smoke Test")
|
||||
print("=" * 60)
|
||||
|
||||
# Generate unique test email
|
||||
test_email = generate_unique_email()
|
||||
print(f"📧 Test email: {test_email}")
|
||||
|
||||
# Step 1: Register user
|
||||
print("\n1️⃣ Step 1: Registration")
|
||||
reg_result = await call_registration(test_email)
|
||||
if not reg_result["success"]:
|
||||
print("❌ TEST FAILED: Registration failed")
|
||||
return False
|
||||
|
||||
# Wait a moment for email to be sent
|
||||
print("\n⏳ Waiting 3 seconds for email processing...")
|
||||
await asyncio.sleep(3)
|
||||
|
||||
# Step 2: Get verification token
|
||||
print("\n2️⃣ Step 2: Token Retrieval")
|
||||
|
||||
# Try database first (more reliable)
|
||||
token = await get_verification_token_from_db(test_email)
|
||||
|
||||
# If not found in DB, try Mailpit
|
||||
if not token:
|
||||
print("⚠️ Token not found in DB, trying Mailpit...")
|
||||
token = await get_verification_token_from_mailpit(test_email)
|
||||
|
||||
if not token:
|
||||
print("❌ TEST FAILED: Could not retrieve verification token")
|
||||
return False
|
||||
|
||||
# Step 3: Verify email
|
||||
print("\n3️⃣ Step 3: Email Verification")
|
||||
verify_success = await verify_email(token)
|
||||
if not verify_success:
|
||||
print("❌ TEST FAILED: Email verification failed")
|
||||
return False
|
||||
|
||||
# Step 4: Check user activation
|
||||
print("\n4️⃣ Step 4: Activation Verification")
|
||||
await asyncio.sleep(2) # Give DB time to update
|
||||
is_active = await check_user_activated(test_email)
|
||||
|
||||
if not is_active:
|
||||
print("❌ TEST FAILED: User not activated after verification")
|
||||
return False
|
||||
|
||||
# Final report
|
||||
print("\n" + "=" * 60)
|
||||
print("✅ TEST PASSED: Registration-to-Activation flow is 100% OK")
|
||||
print("=" * 60)
|
||||
print(f"Summary:")
|
||||
print(f" • Test email: {test_email}")
|
||||
print(f" • Registration: ✅ Success")
|
||||
print(f" • Token retrieval: ✅ Success")
|
||||
print(f" • Email verification: ✅ Success")
|
||||
print(f" • User activation: ✅ Success")
|
||||
print("=" * 60)
|
||||
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Install asyncpg if needed
|
||||
try:
|
||||
import asyncpg
|
||||
except ImportError:
|
||||
print("⚠️ asyncpg not installed. Installing...")
|
||||
import subprocess
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", "asyncpg"])
|
||||
import asyncpg
|
||||
|
||||
# Run the test
|
||||
success = asyncio.run(main())
|
||||
sys.exit(0 if success else 1)
|
||||
Reference in New Issue
Block a user