#!/usr/bin/env python3 """ WHOOSH Integration Test Suite - Phase 5 Comprehensive Testing Tests all major system components and their interactions. """ import asyncio import json import os import sys import time import requests import subprocess from pathlib import Path from typing import Dict, List, Optional, Tuple from datetime import datetime class WHOOSHIntegrationTester: """Comprehensive integration test suite for WHOOSH system""" def __init__(self): self.backend_url = "http://localhost:8087" self.frontend_url = "http://localhost:3000" self.gitea_url = "http://gitea.home.deepblack.cloud" self.test_results = [] self.failed_tests = [] def log_test(self, test_name: str, success: bool, message: str, details: Optional[Dict] = None): """Log test results""" result = { 'test': test_name, 'success': success, 'message': message, 'timestamp': datetime.now().isoformat(), 'details': details or {} } self.test_results.append(result) status = "āœ…" if success else "āŒ" print(f"{status} {test_name}: {message}") if not success: self.failed_tests.append(result) if details: print(f" Details: {json.dumps(details, indent=2)}") def test_system_health(self) -> bool: """Test basic system health and connectivity""" print("\nšŸ„ SYSTEM HEALTH CHECKS") print("=" * 50) all_passed = True # Test 1: Backend API Health try: response = requests.get(f"{self.backend_url}/health", timeout=5) success = response.status_code == 200 data = response.json() if success else None self.log_test( "Backend Health Check", success, f"Status {response.status_code}" + (f" - Version {data.get('version')}" if data else ""), {'status_code': response.status_code, 'response': data} ) all_passed &= success except Exception as e: self.log_test("Backend Health Check", False, f"Connection failed: {e}") all_passed = False # Test 2: Database Connection (through API) try: response = requests.get(f"{self.backend_url}/api/health", timeout=10) success = response.status_code == 200 data = response.json() if success else None self.log_test( "Database Health Check", success, f"Database connectivity: {'OK' if success else 'FAILED'}", {'status_code': response.status_code, 'components': data.get('components', []) if data else []} ) # Note: Database test might fail in development environment, don't mark as critical except Exception as e: self.log_test("Database Health Check", False, f"API call failed: {e}") # Test 3: GITEA Connectivity try: response = requests.get(f"{self.gitea_url}/api/v1/version", timeout=5) success = response.status_code == 200 data = response.json() if success else None self.log_test( "GITEA Connectivity", success, f"GITEA version: {data.get('version', 'Unknown') if data else 'Unavailable'}", {'status_code': response.status_code, 'version_info': data} ) all_passed &= success except Exception as e: self.log_test("GITEA Connectivity", False, f"Connection failed: {e}") all_passed = False # Test 4: File System Permissions try: templates_path = Path("/home/tony/chorus/project-queues/active/WHOOSH/backend/templates") can_read = templates_path.exists() and templates_path.is_dir() can_write = os.access(templates_path.parent, os.W_OK) self.log_test( "File System Access", can_read and can_write, f"Templates directory: {'āœ“ Read' if can_read else 'āœ— Read'}, {'āœ“ Write' if can_write else 'āœ— Write'}", {'templates_exist': can_read, 'can_write': can_write, 'path': str(templates_path)} ) all_passed &= (can_read and can_write) except Exception as e: self.log_test("File System Access", False, f"Permission check failed: {e}") all_passed = False return all_passed def test_template_system(self) -> bool: """Test the template system functionality""" print("\nšŸ“‹ TEMPLATE SYSTEM TESTS") print("=" * 50) all_passed = True # Test 1: Template API Endpoint try: response = requests.get(f"{self.backend_url}/api/templates", timeout=10) success = response.status_code == 200 data = response.json() if success else None template_count = len(data.get('templates', [])) if data else 0 self.log_test( "Template API Listing", success, f"Found {template_count} templates", {'status_code': response.status_code, 'template_count': template_count} ) all_passed &= success # Test 2: Template Details if success and template_count > 0: template_id = data['templates'][0]['template_id'] detail_response = requests.get(f"{self.backend_url}/api/templates/{template_id}", timeout=10) detail_success = detail_response.status_code == 200 detail_data = detail_response.json() if detail_success else None file_count = len(detail_data.get('starter_files', {})) if detail_data else 0 self.log_test( "Template Detail Retrieval", detail_success, f"Template '{template_id}' has {file_count} starter files", {'template_id': template_id, 'file_count': file_count} ) all_passed &= detail_success except Exception as e: self.log_test("Template API Listing", False, f"API call failed: {e}") all_passed = False # Test 3: Template File Generation try: # Test the template service directly (simulated) templates_path = Path("/home/tony/chorus/project-queues/active/WHOOSH/backend/templates") template_dirs = [d for d in templates_path.iterdir() if d.is_dir()] valid_templates = 0 for template_dir in template_dirs: metadata_file = template_dir / "template.json" files_dir = template_dir / "files" if metadata_file.exists() and files_dir.exists(): valid_templates += 1 self.log_test( "Template File Structure", valid_templates > 0, f"{valid_templates} valid templates with complete file structures", {'valid_templates': valid_templates, 'total_dirs': len(template_dirs)} ) all_passed &= (valid_templates > 0) except Exception as e: self.log_test("Template File Structure", False, f"File system check failed: {e}") all_passed = False return all_passed def test_gitea_integration(self) -> bool: """Test GITEA integration functionality""" print("\nšŸ”— GITEA INTEGRATION TESTS") print("=" * 50) all_passed = True # Test 1: GITEA API Token Validation try: # This would test the GITEA service but we need the token # For now, just test that the service endpoints exist response = requests.get(f"{self.backend_url}/api/projects", timeout=5) success = response.status_code in [200, 401] # 401 is OK, means auth is working self.log_test( "GITEA Integration Endpoints", success, f"Projects API accessible (Status: {response.status_code})", {'status_code': response.status_code} ) all_passed &= success except Exception as e: self.log_test("GITEA Integration Endpoints", False, f"Endpoint test failed: {e}") all_passed = False # Test 2: Repository Creation Logic (Mock) try: # Test the project setup endpoint structure test_payload = { "project_info": {"name": "test-integration-project", "description": "Test project"}, "git_config": {"repo_type": "new", "repo_name": "test-repo"}, "age_config": {"generate_new_key": True}, "member_config": {"initial_members": []}, "bzzz_config": {"enable_bzzz": False}, "advanced_config": {"project_visibility": "private"} } # Don't actually create, just test the endpoint structure response = requests.post( f"{self.backend_url}/api/projects/setup", json=test_payload, timeout=5 ) # We expect this to fail due to auth/db, but not due to malformed request success = response.status_code in [401, 422, 503] # Auth, validation, or service errors are OK self.log_test( "Project Setup Endpoint", success, f"Endpoint properly structured (Status: {response.status_code})", {'status_code': response.status_code, 'expected_errors': [401, 422, 503]} ) except Exception as e: self.log_test("Project Setup Endpoint", False, f"Endpoint test failed: {e}") all_passed = False return all_passed def test_security_features(self) -> bool: """Test security features and configurations""" print("\nšŸ” SECURITY FEATURE TESTS") print("=" * 50) all_passed = True # Test 1: Age Key Service Structure try: # Test age key endpoint accessibility response = requests.get(f"{self.backend_url}/api/crypto/generate-age-keys", timeout=5) # We expect this to require authentication or specific methods success = response.status_code in [401, 405, 422] self.log_test( "Age Key Endpoints", success, f"Age key endpoints properly secured (Status: {response.status_code})", {'status_code': response.status_code} ) except Exception as e: self.log_test("Age Key Endpoints", False, f"Security test failed: {e}") all_passed = False # Test 2: CORS Configuration try: response = requests.options(f"{self.backend_url}/api/templates", timeout=5) headers = response.headers has_cors = 'Access-Control-Allow-Origin' in headers self.log_test( "CORS Configuration", has_cors, f"CORS headers {'present' if has_cors else 'missing'}", {'cors_headers': dict(headers) if has_cors else {}} ) all_passed &= has_cors except Exception as e: self.log_test("CORS Configuration", False, f"CORS test failed: {e}") all_passed = False # Test 3: API Documentation Security try: # Test that docs are accessible but properly configured response = requests.get(f"{self.backend_url}/docs", timeout=5) success = response.status_code == 200 self.log_test( "API Documentation", success, f"OpenAPI documentation {'accessible' if success else 'unavailable'}", {'status_code': response.status_code} ) except Exception as e: self.log_test("API Documentation", False, f"Documentation test failed: {e}") all_passed = False return all_passed def test_performance_baseline(self) -> bool: """Test basic performance characteristics""" print("\n⚔ PERFORMANCE BASELINE TESTS") print("=" * 50) all_passed = True # Test 1: API Response Times endpoints_to_test = [ ("/health", "Health Check"), ("/api/templates", "Template Listing"), ("/docs", "API Documentation") ] for endpoint, name in endpoints_to_test: try: start_time = time.time() response = requests.get(f"{self.backend_url}{endpoint}", timeout=10) response_time = time.time() - start_time # Consider under 2 seconds as acceptable for development success = response_time < 2.0 and response.status_code in [200, 401] self.log_test( f"Response Time - {name}", success, f"{response_time:.2f}s (Status: {response.status_code})", {'response_time': response_time, 'status_code': response.status_code} ) all_passed &= success except Exception as e: self.log_test(f"Response Time - {name}", False, f"Performance test failed: {e}") all_passed = False return all_passed def run_all_tests(self) -> Dict: """Run all integration tests and return summary""" print("šŸš€ WHOOSH INTEGRATION TEST SUITE") print("=" * 60) print(f"Starting comprehensive testing at {datetime.now().isoformat()}") print() start_time = time.time() # Run all test suites test_suites = [ ("System Health", self.test_system_health), ("Template System", self.test_template_system), ("GITEA Integration", self.test_gitea_integration), ("Security Features", self.test_security_features), ("Performance Baseline", self.test_performance_baseline) ] suite_results = {} overall_success = True for suite_name, test_func in test_suites: try: suite_success = test_func() suite_results[suite_name] = suite_success overall_success &= suite_success except Exception as e: print(f"āŒ {suite_name} suite failed: {e}") suite_results[suite_name] = False overall_success = False # Generate final report end_time = time.time() duration = end_time - start_time print("\nšŸ“Š TEST SUMMARY") print("=" * 60) total_tests = len(self.test_results) passed_tests = len([r for r in self.test_results if r['success']]) failed_tests = len(self.failed_tests) print(f"Total Tests: {total_tests}") print(f"Passed: {passed_tests}") print(f"Failed: {failed_tests}") print(f"Success Rate: {(passed_tests/total_tests*100):.1f}%") print(f"Duration: {duration:.2f}s") print(f"\nSuite Results:") for suite, success in suite_results.items(): status = "āœ… PASS" if success else "āŒ FAIL" print(f" {status} {suite}") if self.failed_tests: print(f"\nāŒ FAILED TESTS ({len(self.failed_tests)}):") for test in self.failed_tests: print(f" • {test['test']}: {test['message']}") return { 'overall_success': overall_success, 'total_tests': total_tests, 'passed_tests': passed_tests, 'failed_tests': failed_tests, 'success_rate': passed_tests/total_tests*100, 'duration': duration, 'suite_results': suite_results, 'detailed_results': self.test_results, 'failed_test_details': self.failed_tests } def main(): """Main test runner""" tester = WHOOSHIntegrationTester() results = tester.run_all_tests() # Save results to file results_file = f"integration_test_results_{int(time.time())}.json" with open(results_file, 'w') as f: json.dump(results, f, indent=2, default=str) print(f"\nšŸ“„ Detailed results saved to: {results_file}") if results['overall_success']: print("\nšŸŽ‰ ALL INTEGRATION TESTS PASSED!") sys.exit(0) else: print(f"\nāš ļø SOME TESTS FAILED - Success rate: {results['success_rate']:.1f}%") sys.exit(1) if __name__ == "__main__": main()