""" API 테스트 스크립트 Usage: python test_api.py """ import asyncio import httpx from datetime import datetime BASE_URL = "http://localhost:8101" API_BASE = f"{BASE_URL}/api/v1" # Test credentials ADMIN_USER = { "username": "admin", "password": "admin123456", "email": "admin@example.com", "full_name": "Admin User", "role": "admin" } EDITOR_USER = { "username": "editor", "password": "editor123456", "email": "editor@example.com", "full_name": "Editor User", "role": "editor" } # Global token storage admin_token = None editor_token = None async def print_section(title: str): """Print a test section header""" print(f"\n{'='*80}") print(f" {title}") print(f"{'='*80}\n") async def test_health(): """Test basic health check""" await print_section("1. Health Check") async with httpx.AsyncClient() as client: try: response = await client.get(f"{BASE_URL}/") print(f"✅ Server is running") print(f" Status: {response.status_code}") print(f" Response: {response.json()}") return True except Exception as e: print(f"❌ Server is not running: {e}") return False async def create_admin_user(): """Create initial admin user directly in database""" await print_section("2. Creating Admin User") from motor.motor_asyncio import AsyncIOMotorClient from app.core.auth import get_password_hash from datetime import datetime try: client = AsyncIOMotorClient("mongodb://localhost:27017") db = client.news_engine_console_db # Check if admin exists existing = await db.users.find_one({"username": ADMIN_USER["username"]}) if existing: print(f"✅ Admin user already exists") return True # Create admin user user_data = { "username": ADMIN_USER["username"], "email": ADMIN_USER["email"], "full_name": ADMIN_USER["full_name"], "role": ADMIN_USER["role"], "hashed_password": get_password_hash(ADMIN_USER["password"]), "disabled": False, "created_at": datetime.utcnow(), "last_login": None } result = await db.users.insert_one(user_data) print(f"✅ Admin user created successfully") print(f" ID: {result.inserted_id}") await client.close() return True except Exception as e: print(f"❌ Failed to create admin user: {e}") return False async def test_login(): """Test login endpoint""" await print_section("3. Testing Login") global admin_token async with httpx.AsyncClient() as client: try: # Test admin login response = await client.post( f"{API_BASE}/users/login", data={ "username": ADMIN_USER["username"], "password": ADMIN_USER["password"] } ) if response.status_code == 200: data = response.json() admin_token = data["access_token"] print(f"✅ Admin login successful") print(f" Token: {admin_token[:50]}...") print(f" Expires in: {data['expires_in']} seconds") return True else: print(f"❌ Admin login failed") print(f" Status: {response.status_code}") print(f" Response: {response.json()}") return False except Exception as e: print(f"❌ Login test failed: {e}") return False async def test_users_api(): """Test Users API endpoints""" await print_section("4. Testing Users API") headers = {"Authorization": f"Bearer {admin_token}"} async with httpx.AsyncClient() as client: try: # Test 1: Get current user print("📝 GET /users/me") response = await client.get(f"{API_BASE}/users/me", headers=headers) print(f" Status: {response.status_code}") if response.status_code == 200: user = response.json() print(f" ✅ Username: {user['username']}, Role: {user['role']}") # Test 2: Get user stats print("\n📝 GET /users/stats") response = await client.get(f"{API_BASE}/users/stats", headers=headers) print(f" Status: {response.status_code}") if response.status_code == 200: stats = response.json() print(f" ✅ Total users: {stats['total_users']}") print(f" ✅ Active: {stats['active_users']}") print(f" ✅ By role: {stats['by_role']}") # Test 3: Create editor user print("\n📝 POST /users/") response = await client.post( f"{API_BASE}/users/", json=EDITOR_USER, headers=headers ) print(f" Status: {response.status_code}") if response.status_code == 201: user = response.json() print(f" ✅ Created user: {user['username']}") # Test 4: List all users print("\n📝 GET /users/") response = await client.get(f"{API_BASE}/users/", headers=headers) print(f" Status: {response.status_code}") if response.status_code == 200: users = response.json() print(f" ✅ Total users: {len(users)}") for user in users: print(f" - {user['username']} ({user['role']})") return True except Exception as e: print(f"❌ Users API test failed: {e}") return False async def test_keywords_api(): """Test Keywords API endpoints""" await print_section("5. Testing Keywords API") headers = {"Authorization": f"Bearer {admin_token}"} async with httpx.AsyncClient() as client: try: # Test 1: Create keywords print("📝 POST /keywords/") test_keywords = [ {"keyword": "도널드 트럼프", "category": "people", "priority": 9}, {"keyword": "일론 머스크", "category": "people", "priority": 8}, {"keyword": "인공지능", "category": "topics", "priority": 10} ] created_ids = [] for kw_data in test_keywords: response = await client.post( f"{API_BASE}/keywords/", json=kw_data, headers=headers ) if response.status_code == 201: keyword = response.json() created_ids.append(keyword["_id"]) print(f" ✅ Created: {keyword['keyword']} (priority: {keyword['priority']})") # Test 2: List keywords print("\n📝 GET /keywords/") response = await client.get(f"{API_BASE}/keywords/", headers=headers) print(f" Status: {response.status_code}") if response.status_code == 200: data = response.json() print(f" ✅ Total keywords: {data['total']}") for kw in data['keywords']: print(f" - {kw['keyword']} ({kw['category']}, priority: {kw['priority']})") # Test 3: Filter by category print("\n📝 GET /keywords/?category=people") response = await client.get( f"{API_BASE}/keywords/", params={"category": "people"}, headers=headers ) if response.status_code == 200: data = response.json() print(f" ✅ People keywords: {data['total']}") # Test 4: Toggle keyword status if created_ids: print(f"\n📝 POST /keywords/{created_ids[0]}/toggle") response = await client.post( f"{API_BASE}/keywords/{created_ids[0]}/toggle", headers=headers ) if response.status_code == 200: keyword = response.json() print(f" ✅ Status changed to: {keyword['status']}") # Test 5: Get keyword stats if created_ids: print(f"\n📝 GET /keywords/{created_ids[0]}/stats") response = await client.get( f"{API_BASE}/keywords/{created_ids[0]}/stats", headers=headers ) if response.status_code == 200: stats = response.json() print(f" ✅ Total articles: {stats['total_articles']}") print(f" ✅ Last 24h: {stats['articles_last_24h']}") return True except Exception as e: print(f"❌ Keywords API test failed: {e}") return False async def test_pipelines_api(): """Test Pipelines API endpoints""" await print_section("6. Testing Pipelines API") headers = {"Authorization": f"Bearer {admin_token}"} async with httpx.AsyncClient() as client: try: # Test 1: Create pipeline print("📝 POST /pipelines/") pipeline_data = { "name": "RSS Collector - Test", "type": "rss_collector", "config": { "interval_minutes": 30, "max_articles": 100 }, "schedule": "*/30 * * * *" } response = await client.post( f"{API_BASE}/pipelines/", json=pipeline_data, headers=headers ) pipeline_id = None if response.status_code == 201: pipeline = response.json() pipeline_id = pipeline["_id"] print(f" ✅ Created: {pipeline['name']}") print(f" ✅ Type: {pipeline['type']}") print(f" ✅ Status: {pipeline['status']}") # Test 2: List pipelines print("\n📝 GET /pipelines/") response = await client.get(f"{API_BASE}/pipelines/", headers=headers) if response.status_code == 200: data = response.json() print(f" ✅ Total pipelines: {data['total']}") # Test 3: Start pipeline if pipeline_id: print(f"\n📝 POST /pipelines/{pipeline_id}/start") response = await client.post( f"{API_BASE}/pipelines/{pipeline_id}/start", headers=headers ) if response.status_code == 200: pipeline = response.json() print(f" ✅ Pipeline status: {pipeline['status']}") # Test 4: Get pipeline stats if pipeline_id: print(f"\n📝 GET /pipelines/{pipeline_id}/stats") response = await client.get( f"{API_BASE}/pipelines/{pipeline_id}/stats", headers=headers ) if response.status_code == 200: stats = response.json() print(f" ✅ Total processed: {stats['total_processed']}") print(f" ✅ Success count: {stats['success_count']}") # Test 5: Get pipeline logs if pipeline_id: print(f"\n📝 GET /pipelines/{pipeline_id}/logs") response = await client.get( f"{API_BASE}/pipelines/{pipeline_id}/logs", headers=headers ) if response.status_code == 200: logs = response.json() print(f" ✅ Total logs: {len(logs)}") # Test 6: Stop pipeline if pipeline_id: print(f"\n📝 POST /pipelines/{pipeline_id}/stop") response = await client.post( f"{API_BASE}/pipelines/{pipeline_id}/stop", headers=headers ) if response.status_code == 200: pipeline = response.json() print(f" ✅ Pipeline status: {pipeline['status']}") return True except Exception as e: print(f"❌ Pipelines API test failed: {e}") return False async def test_applications_api(): """Test Applications API endpoints""" await print_section("7. Testing Applications API") headers = {"Authorization": f"Bearer {admin_token}"} async with httpx.AsyncClient() as client: try: # Test 1: Create application print("📝 POST /applications/") app_data = { "name": "Test Frontend App", "redirect_uris": ["http://localhost:3000/auth/callback"], "grant_types": ["authorization_code", "refresh_token"], "scopes": ["read", "write"] } response = await client.post( f"{API_BASE}/applications/", json=app_data, headers=headers ) app_id = None if response.status_code == 201: app = response.json() app_id = app["_id"] print(f" ✅ Created: {app['name']}") print(f" ✅ Client ID: {app['client_id']}") print(f" ✅ Client Secret: {app['client_secret'][:20]}... (shown once)") # Test 2: List applications print("\n📝 GET /applications/") response = await client.get(f"{API_BASE}/applications/", headers=headers) if response.status_code == 200: apps = response.json() print(f" ✅ Total applications: {len(apps)}") for app in apps: print(f" - {app['name']} ({app['client_id']})") # Test 3: Get application stats print("\n📝 GET /applications/stats") response = await client.get(f"{API_BASE}/applications/stats", headers=headers) if response.status_code == 200: stats = response.json() print(f" ✅ Total applications: {stats['total_applications']}") # Test 4: Regenerate secret if app_id: print(f"\n📝 POST /applications/{app_id}/regenerate-secret") response = await client.post( f"{API_BASE}/applications/{app_id}/regenerate-secret", headers=headers ) if response.status_code == 200: app = response.json() print(f" ✅ New secret: {app['client_secret'][:20]}... (shown once)") return True except Exception as e: print(f"❌ Applications API test failed: {e}") return False async def test_monitoring_api(): """Test Monitoring API endpoints""" await print_section("8. Testing Monitoring API") headers = {"Authorization": f"Bearer {admin_token}"} async with httpx.AsyncClient() as client: try: # Test 1: Health check print("📝 GET /monitoring/health") response = await client.get(f"{API_BASE}/monitoring/health", headers=headers) if response.status_code == 200: health = response.json() print(f" ✅ System status: {health['status']}") print(f" ✅ Components:") for name, component in health['components'].items(): status_icon = "✅" if component.get('status') in ['up', 'healthy'] else "⚠️" print(f" {status_icon} {name}: {component.get('status', 'unknown')}") # Test 2: System metrics print("\n📝 GET /monitoring/metrics") response = await client.get(f"{API_BASE}/monitoring/metrics", headers=headers) if response.status_code == 200: metrics = response.json() print(f" ✅ Metrics collected:") print(f" - Keywords: {metrics['keywords']['total']} (active: {metrics['keywords']['active']})") print(f" - Pipelines: {metrics['pipelines']['total']}") print(f" - Users: {metrics['users']['total']} (active: {metrics['users']['active']})") print(f" - Applications: {metrics['applications']['total']}") # Test 3: Activity logs print("\n📝 GET /monitoring/logs") response = await client.get( f"{API_BASE}/monitoring/logs", params={"limit": 10}, headers=headers ) if response.status_code == 200: data = response.json() print(f" ✅ Total logs: {data['total']}") # Test 4: Database stats print("\n📝 GET /monitoring/database/stats") response = await client.get(f"{API_BASE}/monitoring/database/stats", headers=headers) if response.status_code == 200: stats = response.json() print(f" ✅ Database: {stats.get('database', 'N/A')}") print(f" ✅ Collections: {stats.get('collections', 0)}") print(f" ✅ Data size: {stats.get('data_size', 0)} bytes") # Test 5: Pipeline performance print("\n📝 GET /monitoring/pipelines/performance") response = await client.get( f"{API_BASE}/monitoring/pipelines/performance", params={"hours": 24}, headers=headers ) if response.status_code == 200: perf = response.json() print(f" ✅ Period: {perf['period_hours']} hours") print(f" ✅ Pipelines tracked: {len(perf['pipelines'])}") # Test 6: Error summary print("\n📝 GET /monitoring/errors/summary") response = await client.get( f"{API_BASE}/monitoring/errors/summary", params={"hours": 24}, headers=headers ) if response.status_code == 200: summary = response.json() print(f" ✅ Total errors (24h): {summary['total_errors']}") return True except Exception as e: print(f"❌ Monitoring API test failed: {e}") return False async def print_summary(results: dict): """Print test summary""" await print_section("📊 Test Summary") total = len(results) passed = sum(1 for v in results.values() if v) failed = total - passed print(f"Total Tests: {total}") print(f"✅ Passed: {passed}") print(f"❌ Failed: {failed}") print(f"\nSuccess Rate: {(passed/total)*100:.1f}%\n") print("Detailed Results:") for test_name, result in results.items(): status = "✅ PASS" if result else "❌ FAIL" print(f" {status} - {test_name}") print(f"\n{'='*80}\n") async def main(): """Run all tests""" print("\n" + "="*80) print(" NEWS ENGINE CONSOLE - API Testing") print("="*80) results = {} # Test 1: Health check results["Health Check"] = await test_health() if not results["Health Check"]: print("\n❌ Server is not running. Please start the server first.") return # Test 2: Create admin user results["Create Admin User"] = await create_admin_user() # Test 3: Login results["Authentication"] = await test_login() if not results["Authentication"]: print("\n❌ Login failed. Cannot proceed with API tests.") return # Test 4-8: API endpoints results["Users API"] = await test_users_api() results["Keywords API"] = await test_keywords_api() results["Pipelines API"] = await test_pipelines_api() results["Applications API"] = await test_applications_api() results["Monitoring API"] = await test_monitoring_api() # Print summary await print_summary(results) if __name__ == "__main__": asyncio.run(main())