Files
TimeTracker/tests/test_quick_wins.py
T
Dries Peeters d2cac0b3fa chore: move invoice template and tests; remove obsolete root files
- Move pdf_styles_default.css to app/templates/invoices/
- Move test_logo_pdf.py and test_quick_wins.py to tests/
- Remove fix_expense_schema.sql, temp_migration.sql, packages.txt,
  install_log.txt, temp_translated.txt
2026-03-15 10:16:49 +01:00

292 lines
10 KiB
Python

#!/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())