#!/usr/bin/env python3 """ Quick Wins Features - Validation Test Script This script validates that all new features can be imported and basic functionality works without errors. """ import sys import os # Add the app directory to the path sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) def test_imports(): """Test that all new modules can be imported""" print("šŸ” Testing imports...") try: # Test model imports from app.models import TimeEntryTemplate, Activity, SavedFilter, User print("āœ… Models imported successfully") # Test route imports from app.routes.user import user_bp from app.routes.time_entry_templates import time_entry_templates_bp from app.routes.saved_filters import saved_filters_bp print("āœ… Routes imported successfully") # Test utility imports from app.utils.email import mail, init_mail, send_email from app.utils.excel_export import create_time_entries_excel, create_project_report_excel from app.utils.scheduled_tasks import scheduler, check_overdue_invoices, register_scheduled_tasks print("āœ… Utilities imported successfully") return True except ImportError as e: print(f"āŒ Import error: {e}") return False except Exception as e: print(f"āŒ Unexpected error: {e}") return False def test_model_attributes(): """Test that models have expected attributes""" print("\nšŸ” Testing model attributes...") try: from app.models import TimeEntryTemplate, Activity, SavedFilter, User # Test TimeEntryTemplate attributes template_attrs = ['id', 'user_id', 'name', 'project_id', 'task_id', 'default_duration_minutes', 'default_notes', 'tags', 'usage_count', 'last_used_at'] for attr in template_attrs: assert hasattr(TimeEntryTemplate, attr), f"TimeEntryTemplate missing {attr}" print("āœ… TimeEntryTemplate has all attributes") # Test Activity attributes activity_attrs = ['id', 'user_id', 'action', 'entity_type', 'entity_id', 'description', 'metadata', 'created_at'] for attr in activity_attrs: assert hasattr(Activity, attr), f"Activity missing {attr}" print("āœ… Activity has all attributes") # Test SavedFilter attributes filter_attrs = ['id', 'user_id', 'name', 'scope', 'payload', 'is_shared', 'created_at', 'updated_at'] for attr in filter_attrs: assert hasattr(SavedFilter, attr), f"SavedFilter missing {attr}" print("āœ… SavedFilter has all attributes") # Test User new attributes user_new_attrs = ['email_notifications', 'notification_overdue_invoices', 'notification_task_assigned', 'notification_task_comments', 'notification_weekly_summary', 'timezone', 'date_format', 'time_format', 'week_start_day'] for attr in user_new_attrs: assert hasattr(User, attr), f"User missing new attribute {attr}" print("āœ… User has all new preference attributes") return True except AssertionError as e: print(f"āŒ Attribute test failed: {e}") return False except Exception as e: print(f"āŒ Unexpected error: {e}") return False def test_model_methods(): """Test that models have expected methods""" print("\nšŸ” Testing model methods...") try: from app.models import TimeEntryTemplate, Activity # Test TimeEntryTemplate methods template_methods = ['to_dict', 'record_usage', 'increment_usage'] for method in template_methods: assert hasattr(TimeEntryTemplate, method), f"TimeEntryTemplate missing {method}" print("āœ… TimeEntryTemplate has all methods") # Test Activity methods activity_methods = ['log', 'get_recent', 'to_dict'] for method in activity_methods: assert hasattr(Activity, method), f"Activity missing {method}" print("āœ… Activity has all methods") return True except AssertionError as e: print(f"āŒ Method test failed: {e}") return False except Exception as e: print(f"āŒ Unexpected error: {e}") return False def test_blueprint_registration(): """Test that blueprints are properly configured""" print("\nšŸ” Testing blueprint registration...") try: from app.routes.user import user_bp from app.routes.time_entry_templates import time_entry_templates_bp from app.routes.saved_filters import saved_filters_bp # Check blueprint names assert user_bp.name == 'user', "user_bp has wrong name" assert time_entry_templates_bp.name == 'time_entry_templates', "time_entry_templates_bp has wrong name" assert saved_filters_bp.name == 'saved_filters', "saved_filters_bp has wrong name" print("āœ… All blueprints properly configured") return True except AssertionError as e: print(f"āŒ Blueprint test failed: {e}") return False except Exception as e: print(f"āŒ Unexpected error: {e}") return False def test_utility_functions(): """Test that utility functions exist""" print("\nšŸ” Testing utility functions...") try: from app.utils.email import init_mail, send_email from app.utils.excel_export import create_time_entries_excel, create_project_report_excel from app.utils.scheduled_tasks import register_scheduled_tasks, check_overdue_invoices # Check that functions are callable assert callable(init_mail), "init_mail is not callable" assert callable(send_email), "send_email is not callable" assert callable(create_time_entries_excel), "create_time_entries_excel is not callable" assert callable(create_project_report_excel), "create_project_report_excel is not callable" assert callable(register_scheduled_tasks), "register_scheduled_tasks is not callable" assert callable(check_overdue_invoices), "check_overdue_invoices is not callable" print("āœ… All utility functions are callable") return True except AssertionError as e: print(f"āŒ Utility function test failed: {e}") return False except Exception as e: print(f"āŒ Unexpected error: {e}") return False def test_template_files(): """Test that template files exist""" print("\nšŸ” Testing template files...") template_files = [ 'app/templates/user/settings.html', 'app/templates/user/profile.html', 'app/templates/email/overdue_invoice.html', 'app/templates/email/task_assigned.html', 'app/templates/email/weekly_summary.html', 'app/templates/email/comment_mention.html', 'app/templates/time_entry_templates/list.html', 'app/templates/time_entry_templates/create.html', 'app/templates/time_entry_templates/edit.html', 'app/templates/saved_filters/list.html', 'app/templates/components/save_filter_widget.html', 'app/templates/components/bulk_actions_widget.html', 'app/templates/components/keyboard_shortcuts_help.html', ] missing = [] for template in template_files: if not os.path.exists(template): missing.append(template) if missing: print(f"āŒ Missing templates: {', '.join(missing)}") return False else: print(f"āœ… All {len(template_files)} template files exist") return True def test_migration_file(): """Test that migration file exists and has correct structure""" print("\nšŸ” Testing migration file...") migration_file = 'migrations/versions/add_quick_wins_features.py' if not os.path.exists(migration_file): print(f"āŒ Migration file not found: {migration_file}") return False try: with open(migration_file, 'r') as f: content = f.read() # Check for required elements required = [ "revision = '022'", "down_revision = '021'", 'def upgrade():', 'def downgrade():', 'time_entry_templates', 'activities', ] for req in required: if req not in content: print(f"āŒ Migration missing required element: {req}") return False print("āœ… Migration file is valid") return True except Exception as e: print(f"āŒ Error reading migration file: {e}") return False def main(): """Run all tests""" print("="*60) print("šŸš€ Quick Wins Features - Validation Test") print("="*60) tests = [ ("Imports", test_imports), ("Model Attributes", test_model_attributes), ("Model Methods", test_model_methods), ("Blueprint Registration", test_blueprint_registration), ("Utility Functions", test_utility_functions), ("Template Files", test_template_files), ("Migration File", test_migration_file), ] results = [] for test_name, test_func in tests: try: result = test_func() results.append((test_name, result)) except Exception as e: print(f"\nāŒ Test '{test_name}' crashed: {e}") results.append((test_name, False)) # Summary print("\n" + "="*60) print("šŸ“Š Test Summary") print("="*60) passed = sum(1 for _, result in results if result) total = len(results) for test_name, result in results: status = "āœ… PASS" if result else "āŒ FAIL" print(f"{status} - {test_name}") print("="*60) print(f"Results: {passed}/{total} tests passed ({passed/total*100:.0f}%)") print("="*60) if passed == total: print("\nšŸŽ‰ All tests passed! Ready for deployment.") return 0 else: print(f"\nāš ļø {total - passed} test(s) failed. Please fix before deployment.") return 1 if __name__ == '__main__': exit(main())