#!/usr/bin/env python3 """ Test script to validate refactored backend endpoints Tests all CRUD operations for profiles, songs, and plans """ import requests import json import sys from datetime import datetime BASE_URL = "http://localhost:8080/api" session = requests.Session() # Color output GREEN = '\033[92m' RED = '\033[91m' RESET = '\033[0m' BLUE = '\033[94m' test_results = [] def log_test(name, passed, details=""): """Log test result""" status = f"{GREEN}✓ PASS{RESET}" if passed else f"{RED}✗ FAIL{RESET}" print(f"{status} - {name}") if details and not passed: print(f" {details}") test_results.append((name, passed, details)) def test_health(): """Test health endpoint""" try: response = session.get(f"{BASE_URL}/health") passed = response.status_code == 200 and response.json().get('status') == 'ok' log_test("Health Check", passed) return passed except Exception as e: log_test("Health Check", False, str(e)) return False def test_profile_crud(): """Test profile CRUD operations""" print(f"\n{BLUE}=== Testing Profile CRUD ==={RESET}") # CREATE try: profile_data = { "name": "Test Profile", "first_name": "Test", "last_name": "User", "email": "test@example.com", "default_key": "C" } response = session.post(f"{BASE_URL}/profiles", json=profile_data) passed = response.status_code == 200 profile_id = response.json().get('id') if passed else None log_test("Profile Create", passed, response.text if not passed else "") if not passed: return False except Exception as e: log_test("Profile Create", False, str(e)) return False # READ (GET ALL) try: response = session.get(f"{BASE_URL}/profiles") passed = response.status_code == 200 and isinstance(response.json(), list) log_test("Profile List", passed, response.text if not passed else "") except Exception as e: log_test("Profile List", False, str(e)) return False # UPDATE try: update_data = {"notes": "Updated notes from refactored test"} response = session.put(f"{BASE_URL}/profiles/{profile_id}", json=update_data) passed = response.status_code == 200 log_test("Profile Update", passed, response.text if not passed else "") except Exception as e: log_test("Profile Update", False, str(e)) return False # DELETE try: response = session.delete(f"{BASE_URL}/profiles/{profile_id}") passed = response.status_code == 200 log_test("Profile Delete", passed, response.text if not passed else "") except Exception as e: log_test("Profile Delete", False, str(e)) return False return True def test_song_crud(): """Test song CRUD operations""" print(f"\n{BLUE}=== Testing Song CRUD ==={RESET}") # CREATE try: song_data = { "title": "Test Song", "artist": "Test Artist", "lyrics": "Test lyrics content", "chords": "C G Am F" } response = session.post(f"{BASE_URL}/songs", json=song_data) passed = response.status_code == 200 song_id = response.json().get('id') if passed else None log_test("Song Create", passed, response.text if not passed else "") if not passed: return False except Exception as e: log_test("Song Create", False, str(e)) return False # READ (SEARCH) try: response = session.get(f"{BASE_URL}/songs?q=Test") passed = response.status_code == 200 and isinstance(response.json(), list) log_test("Song Search", passed, response.text if not passed else "") except Exception as e: log_test("Song Search", False, str(e)) return False # READ (GET ONE) try: response = session.get(f"{BASE_URL}/songs/{song_id}") passed = response.status_code == 200 log_test("Song Get", passed, response.text if not passed else "") except Exception as e: log_test("Song Get", False, str(e)) return False # UPDATE try: update_data = {"chords": "C G Am F G"} response = session.put(f"{BASE_URL}/songs/{song_id}", json=update_data) passed = response.status_code == 200 log_test("Song Update", passed, response.text if not passed else "") except Exception as e: log_test("Song Update", False, str(e)) return False # DELETE try: response = session.delete(f"{BASE_URL}/songs/{song_id}") passed = response.status_code == 200 log_test("Song Delete", passed, response.text if not passed else "") except Exception as e: log_test("Song Delete", False, str(e)) return False return True def test_plan_crud(): """Test plan CRUD operations""" print(f"\n{BLUE}=== Testing Plan CRUD ==={RESET}") # CREATE try: plan_data = { "date": datetime.now().strftime("%Y-%m-%d"), "notes": "Test plan from refactored code" } response = session.post(f"{BASE_URL}/plans", json=plan_data) passed = response.status_code == 200 plan_id = response.json().get('id') if passed else None log_test("Plan Create", passed, response.text if not passed else "") if not passed: return False except Exception as e: log_test("Plan Create", False, str(e)) return False # READ try: response = session.get(f"{BASE_URL}/plans") passed = response.status_code == 200 and isinstance(response.json(), list) log_test("Plan List", passed, response.text if not passed else "") except Exception as e: log_test("Plan List", False, str(e)) return False # READ (GET ONE) try: response = session.get(f"{BASE_URL}/plans/{plan_id}") passed = response.status_code == 200 log_test("Plan Get", passed, response.text if not passed else "") except Exception as e: log_test("Plan Get", False, str(e)) return False # UPDATE try: update_data = {"notes": "Updated plan notes"} response = session.put(f"{BASE_URL}/plans/{plan_id}", json=update_data) passed = response.status_code == 200 log_test("Plan Update", passed, response.text if not passed else "") except Exception as e: log_test("Plan Update", False, str(e)) return False # DELETE try: response = session.delete(f"{BASE_URL}/plans/{plan_id}") passed = response.status_code == 200 log_test("Plan Delete", passed, response.text if not passed else "") except Exception as e: log_test("Plan Delete", False, str(e)) return False return True def test_validation(): """Test input validation""" print(f"\n{BLUE}=== Testing Input Validation ==={RESET}") # Test invalid profile (missing name) try: response = session.post(f"{BASE_URL}/profiles", json={}) passed = response.status_code == 400 log_test("Validation: Missing Profile Name", passed) except Exception as e: log_test("Validation: Missing Profile Name", False, str(e)) # Test invalid song (missing title) try: response = session.post(f"{BASE_URL}/songs", json={"title": ""}) passed = response.status_code == 400 log_test("Validation: Missing Song Title", passed) except Exception as e: log_test("Validation: Missing Song Title", False, str(e)) # Test invalid ID format try: long_id = "x" * 300 response = session.put(f"{BASE_URL}/profiles/{long_id}", json={}) passed = response.status_code == 400 log_test("Validation: Invalid ID Format", passed, f"Expected 400, got {response.status_code}") except Exception as e: log_test("Validation: Invalid ID Format", False, str(e)) def print_summary(): """Print test summary""" print(f"\n{BLUE}{'='*60}{RESET}") print(f"{BLUE}TEST SUMMARY{RESET}") print(f"{BLUE}{'='*60}{RESET}") passed = sum(1 for _, p, _ in test_results if p) total = len(test_results) print(f"Total Tests: {total}") print(f"Passed: {GREEN}{passed}{RESET}") print(f"Failed: {RED}{total - passed}{RESET}") print(f"Success Rate: {(passed/total*100):.1f}%") if passed == total: print(f"\n{GREEN}✓ ALL TESTS PASSED - Refactoring successful!{RESET}") return 0 else: print(f"\n{RED}✗ Some tests failed - Review errors above{RESET}") return 1 if __name__ == "__main__": print(f"{BLUE}{'='*60}{RESET}") print(f"{BLUE}Refactored Backend Test Suite{RESET}") print(f"{BLUE}{'='*60}{RESET}") # Run tests test_health() test_profile_crud() test_song_crud() test_plan_crud() test_validation() # Print summary and exit sys.exit(print_summary())