""" Test script for Phase 3.1 - Chore Completion Logging This script tests the new completion logging system without needing the frontend. Run this after running the migration to verify everything works. """ import sqlite3 import sys from pathlib import Path from datetime import datetime, timedelta # Add parent directory to path sys.path.insert(0, str(Path(__file__).parent)) def test_database_structure(): """Test that the database table was created correctly.""" print("\n" + "="*70) print("TEST 1: Database Structure") print("="*70) db_path = Path(__file__).parent / "backend" / "data" / "family_hub.db" if not db_path.exists(): print(f"โŒ Database not found at: {db_path}") return False conn = sqlite3.connect(db_path) cursor = conn.cursor() try: # Check table exists cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='chore_completion_logs'") table = cursor.fetchone() if not table: print("โŒ Table 'chore_completion_logs' not found!") return False print("โœ… Table 'chore_completion_logs' exists") # Check structure cursor.execute("PRAGMA table_info(chore_completion_logs)") columns = cursor.fetchall() expected_columns = [ 'id', 'chore_id', 'user_id', 'completed_at', 'notes', 'verified_by_user_id', 'created_at' ] actual_columns = [col[1] for col in columns] print(f"\n๐Ÿ“‹ Table Columns:") for col in columns: print(f" - {col[1]} ({col[2]})") missing = set(expected_columns) - set(actual_columns) if missing: print(f"\nโŒ Missing columns: {missing}") return False print("\nโœ… All expected columns present") # Check indexes cursor.execute("SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='chore_completion_logs'") indexes = cursor.fetchall() print(f"\n๐Ÿ“Š Indexes ({len(indexes)}):") for idx in indexes: print(f" - {idx[0]}") if len(indexes) >= 3: print("โœ… Expected indexes created") else: print(f"โš ๏ธ Expected at least 3 indexes, found {len(indexes)}") return True except Exception as e: print(f"โŒ Error: {e}") return False finally: conn.close() def test_sample_data_insertion(): """Test inserting sample completion logs.""" print("\n" + "="*70) print("TEST 2: Sample Data Insertion") print("="*70) db_path = Path(__file__).parent / "backend" / "data" / "family_hub.db" conn = sqlite3.connect(db_path) cursor = conn.cursor() try: # Get first user and first chore cursor.execute("SELECT id, username FROM users LIMIT 1") user = cursor.fetchone() cursor.execute("SELECT id, title FROM chores LIMIT 1") chore = cursor.fetchone() if not user or not chore: print("โš ๏ธ No users or chores found - create some first!") return False print(f"๐Ÿ“ Using User: {user[1]} (ID: {user[0]})") print(f"๐Ÿ“ Using Chore: {chore[1]} (ID: {chore[0]})") # Insert a test completion now = datetime.utcnow() cursor.execute(""" INSERT INTO chore_completion_logs (chore_id, user_id, completed_at, notes, created_at) VALUES (?, ?, ?, ?, ?) """, (chore[0], user[0], now, "Test completion from validation script", now)) log_id = cursor.lastrowid conn.commit() print(f"โœ… Inserted test completion log (ID: {log_id})") # Verify insertion cursor.execute("SELECT * FROM chore_completion_logs WHERE id = ?", (log_id,)) log = cursor.fetchone() if log: print(f"โœ… Verified: Log can be retrieved") print(f" - ID: {log[0]}") print(f" - Chore ID: {log[1]}") print(f" - User ID: {log[2]}") print(f" - Completed At: {log[3]}") print(f" - Notes: {log[4]}") else: print("โŒ Could not retrieve inserted log") return False # Clean up test data cursor.execute("DELETE FROM chore_completion_logs WHERE id = ?", (log_id,)) conn.commit() print(f"๐Ÿงน Cleaned up test data") return True except Exception as e: print(f"โŒ Error: {e}") conn.rollback() return False finally: conn.close() def test_query_performance(): """Test query performance with existing data.""" print("\n" + "="*70) print("TEST 3: Query Performance") print("="*70) db_path = Path(__file__).parent / "backend" / "data" / "family_hub.db" conn = sqlite3.connect(db_path) cursor = conn.cursor() try: # Count total logs cursor.execute("SELECT COUNT(*) FROM chore_completion_logs") total_logs = cursor.fetchone()[0] print(f"๐Ÿ“Š Total completion logs: {total_logs}") if total_logs == 0: print("โ„น๏ธ No completion logs yet - this is expected for new installation") return True # Test date range query week_ago = datetime.utcnow() - timedelta(days=7) cursor.execute(""" SELECT COUNT(*) FROM chore_completion_logs WHERE completed_at >= ? """, (week_ago,)) week_logs = cursor.fetchone()[0] print(f"๐Ÿ“Š Completions in last 7 days: {week_logs}") # Test user grouping cursor.execute(""" SELECT user_id, COUNT(*) as count FROM chore_completion_logs GROUP BY user_id ORDER BY count DESC """) user_stats = cursor.fetchall() if user_stats: print(f"\n๐Ÿ“Š Completions by User:") for user_id, count in user_stats: cursor.execute("SELECT username FROM users WHERE id = ?", (user_id,)) username = cursor.fetchone() if username: print(f" - {username[0]}: {count} completions") print("\nโœ… Query performance looks good!") return True except Exception as e: print(f"โŒ Error: {e}") return False finally: conn.close() def test_foreign_key_constraints(): """Test that foreign key constraints are working.""" print("\n" + "="*70) print("TEST 4: Foreign Key Constraints") print("="*70) db_path = Path(__file__).parent / "backend" / "data" / "family_hub.db" conn = sqlite3.connect(db_path) # Enable foreign keys conn.execute("PRAGMA foreign_keys = ON") cursor = conn.cursor() try: # Try to insert with invalid user_id now = datetime.utcnow() try: cursor.execute(""" INSERT INTO chore_completion_logs (chore_id, user_id, completed_at, created_at) VALUES (999999, 999999, ?, ?) """, (now, now)) conn.commit() print("โš ๏ธ Foreign key constraints may not be enforced") # Clean up cursor.execute("DELETE FROM chore_completion_logs WHERE user_id = 999999") conn.commit() except sqlite3.IntegrityError: print("โœ… Foreign key constraints are working!") print(" (Correctly rejected invalid user_id)") return True except Exception as e: print(f"โŒ Error: {e}") return False finally: conn.close() def main(): """Run all tests.""" print("\n" + "="*70) print("PHASE 3.1 - CHORE COMPLETION LOGGING") print("Validation Test Suite") print("="*70) tests = [ test_database_structure, test_sample_data_insertion, test_query_performance, test_foreign_key_constraints ] passed = 0 failed = 0 for test in tests: try: if test(): passed += 1 else: failed += 1 except Exception as e: print(f"โŒ Test failed with exception: {e}") failed += 1 print("\n" + "="*70) print("TEST RESULTS") print("="*70) print(f"โœ… Passed: {passed}") print(f"โŒ Failed: {failed}") print(f"๐Ÿ“Š Total: {passed + failed}") if failed == 0: print("\n๐ŸŽ‰ All tests passed! Phase 3.1 backend is ready!") print("\nNext steps:") print("1. Restart your backend: stop-all.bat && start-backend.bat") print("2. Test the API endpoints (see PHASE_3_1_COMPLETE.md)") print("3. Start building frontend features!") else: print("\nโš ๏ธ Some tests failed. Please review the output above.") print("="*70 + "\n") if __name__ == "__main__": main()