new folder structure

This commit is contained in:
2025-09-29 09:17:13 +02:00
parent 38117ab875
commit 78fc6068fb
197 changed files with 3490 additions and 1117 deletions

1
tests/unit/__init__.py Normal file
View File

@@ -0,0 +1 @@
# Unit test package

View File

@@ -0,0 +1,593 @@
"""
Unit Tests for Core Functionality
This module contains unit tests for the core components of the AniWorld application,
including series management, download operations, and API functionality.
"""
import unittest
import os
import sys
import tempfile
import shutil
import sqlite3
import json
from unittest.mock import Mock, MagicMock, patch, call
from datetime import datetime, timedelta
import threading
# Add parent directory to path for imports
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
# Import core modules
from src.server.core.entities.series import Serie
from src.server.core.entities.SerieList import SerieList
from src.server.infrastructure.file_system.SerieScanner import SerieScanner
# TODO: Fix imports - these modules may not exist or may be in different locations
# from database_manager import DatabaseManager, AnimeMetadata, EpisodeMetadata, BackupManager
# from error_handler import ErrorRecoveryManager, RetryMechanism, NetworkHealthChecker
# from performance_optimizer import SpeedLimiter, DownloadCache, MemoryMonitor
# from api_integration import WebhookManager, ExportManager
class TestSerie(unittest.TestCase):
"""Test cases for Serie class."""
def setUp(self):
"""Set up test fixtures."""
self.test_key = "test-key"
self.test_name = "Test Anime"
self.test_site = "test-site"
self.test_folder = "test_folder"
self.test_episodes = {1: [1], 2: [2]}
def test_serie_initialization(self):
"""Test Serie object initialization."""
serie = Serie(self.test_key, self.test_name, self.test_site, self.test_folder, self.test_episodes)
self.assertEqual(serie.key, self.test_key)
self.assertEqual(serie.name, self.test_name)
self.assertEqual(serie.site, self.test_site)
self.assertEqual(serie.folder, self.test_folder)
self.assertEqual(serie.episodeDict, self.test_episodes)
def test_serie_str_representation(self):
"""Test string representation of Serie."""
serie = Serie(self.test_key, self.test_name, self.test_site, self.test_folder, self.test_episodes)
str_repr = str(serie)
self.assertIn(self.test_name, str_repr)
self.assertIn(self.test_folder, str_repr)
self.assertIn(self.test_key, str_repr)
def test_serie_episode_management(self):
"""Test episode dictionary management."""
serie = Serie(self.test_key, self.test_name, self.test_site, self.test_folder, self.test_episodes)
# Test episode dict
self.assertEqual(len(serie.episodeDict), 2)
self.assertIn(1, serie.episodeDict)
self.assertIn(2, serie.episodeDict)
def test_serie_equality(self):
"""Test Serie equality comparison."""
serie1 = Serie(self.test_key, self.test_name, self.test_site, self.test_folder, self.test_episodes)
serie2 = Serie(self.test_key, self.test_name, self.test_site, self.test_folder, self.test_episodes)
serie3 = Serie("different-key", "Different", self.test_site, self.test_folder, self.test_episodes)
# Should be equal based on key attributes
self.assertEqual(serie1.key, serie2.key)
self.assertEqual(serie1.folder, serie2.folder)
self.assertNotEqual(serie1.key, serie3.key)
class TestSeriesList(unittest.TestCase):
"""Test cases for SeriesList class."""
def setUp(self):
"""Set up test fixtures."""
self.temp_dir = tempfile.mkdtemp()
self.series_list = SerieList(self.temp_dir)
def tearDown(self):
"""Clean up test fixtures."""
shutil.rmtree(self.temp_dir, ignore_errors=True)
def test_series_list_initialization(self):
"""Test SerieList initialization."""
self.assertIsInstance(self.series_list.folderDict, dict)
self.assertEqual(len(self.series_list.folderDict), 0)
def test_add_serie_to_list(self):
"""Test adding serie to list."""
serie = Serie("test-key", "Test", "test-site", "test_folder", {})
self.series_list.add(serie)
self.assertEqual(len(self.series_list.folderDict), 1)
self.assertIn("test_folder", self.series_list.folderDict)
def test_contains_serie(self):
"""Test checking if serie exists."""
serie = Serie("test-key", "Test", "test-site", "test_folder", {})
self.series_list.add(serie)
self.assertTrue(self.series_list.contains("test-key"))
self.assertFalse(self.series_list.contains("nonexistent"))
def test_get_series_with_missing_episodes(self):
"""Test filtering series with missing episodes."""
serie1 = Serie("key1", "Anime 1", "test-site", "folder1", {1: [1], 2: [2]}) # Has missing episodes
serie2 = Serie("key2", "Anime 2", "test-site", "folder2", {}) # No missing episodes
self.series_list.add(serie1)
self.series_list.add(serie2)
missing = self.series_list.GetMissingEpisode()
self.assertEqual(len(missing), 1)
self.assertEqual(missing[0].name, "Anime 1")
class TestDatabaseManager(unittest.TestCase):
"""Test cases for DatabaseManager class."""
def setUp(self):
"""Set up test database."""
self.test_db = tempfile.NamedTemporaryFile(delete=False)
self.test_db.close()
self.db_manager = DatabaseManager(self.test_db.name)
def tearDown(self):
"""Clean up test database."""
self.db_manager.close()
os.unlink(self.test_db.name)
def test_database_initialization(self):
"""Test database initialization."""
# Check if tables exist
with self.db_manager.get_connection() as conn:
cursor = conn.execute("""
SELECT name FROM sqlite_master
WHERE type='table' AND name='anime_metadata'
""")
result = cursor.fetchone()
self.assertIsNotNone(result)
def test_schema_versioning(self):
"""Test schema version management."""
version = self.db_manager.get_current_version()
self.assertIsInstance(version, int)
self.assertGreater(version, 0)
def test_anime_crud_operations(self):
"""Test anime CRUD operations."""
# Create anime
anime = AnimeMetadata(
anime_id="test-123",
name="Test Anime",
folder="test_folder",
key="test-key"
)
# Insert
query = """
INSERT INTO anime_metadata
(anime_id, name, folder, key, created_at, last_updated)
VALUES (?, ?, ?, ?, ?, ?)
"""
params = (
anime.anime_id, anime.name, anime.folder, anime.key,
anime.created_at, anime.last_updated
)
success = self.db_manager.execute_update(query, params)
self.assertTrue(success)
# Read
select_query = "SELECT * FROM anime_metadata WHERE anime_id = ?"
results = self.db_manager.execute_query(select_query, (anime.anime_id,))
self.assertEqual(len(results), 1)
self.assertEqual(results[0]['name'], anime.name)
# Update
update_query = """
UPDATE anime_metadata SET description = ? WHERE anime_id = ?
"""
success = self.db_manager.execute_update(
update_query, ("Updated description", anime.anime_id)
)
self.assertTrue(success)
# Verify update
results = self.db_manager.execute_query(select_query, (anime.anime_id,))
self.assertEqual(results[0]['description'], "Updated description")
# Delete
delete_query = "DELETE FROM anime_metadata WHERE anime_id = ?"
success = self.db_manager.execute_update(delete_query, (anime.anime_id,))
self.assertTrue(success)
# Verify deletion
results = self.db_manager.execute_query(select_query, (anime.anime_id,))
self.assertEqual(len(results), 0)
class TestErrorRecoveryManager(unittest.TestCase):
"""Test cases for ErrorRecoveryManager."""
def setUp(self):
"""Set up error recovery manager."""
self.recovery_manager = ErrorRecoveryManager()
def test_retry_mechanism(self):
"""Test retry mechanism for failed operations."""
retry_mechanism = RetryMechanism(max_retries=3, base_delay=0.1)
# Test successful operation
def success_operation():
return "success"
result = retry_mechanism.execute_with_retry(success_operation)
self.assertEqual(result, "success")
# Test failing operation
call_count = [0]
def failing_operation():
call_count[0] += 1
if call_count[0] < 3:
raise Exception("Temporary failure")
return "success"
result = retry_mechanism.execute_with_retry(failing_operation)
self.assertEqual(result, "success")
self.assertEqual(call_count[0], 3)
def test_network_health_checker(self):
"""Test network health checking."""
checker = NetworkHealthChecker()
# Mock requests for controlled testing
with patch('requests.get') as mock_get:
# Test successful check
mock_response = Mock()
mock_response.status_code = 200
mock_response.raise_for_status.return_value = None
mock_get.return_value = mock_response
is_healthy = checker.check_network_health()
self.assertTrue(is_healthy)
# Test failed check
mock_get.side_effect = Exception("Network error")
is_healthy = checker.check_network_health()
self.assertFalse(is_healthy)
class TestPerformanceOptimizer(unittest.TestCase):
"""Test cases for performance optimization components."""
def setUp(self):
"""Set up performance components."""
self.speed_limiter = SpeedLimiter(max_speed_mbps=10)
self.download_cache = DownloadCache()
def test_speed_limiter(self):
"""Test download speed limiting."""
# Test speed calculation
speed_mbps = self.speed_limiter.calculate_current_speed(1024*1024, 1.0) # 1MB in 1 second
self.assertEqual(speed_mbps, 8.0) # 1MB/s = 8 Mbps
# Test should limit
should_limit = self.speed_limiter.should_limit_speed(15.0) # Above limit
self.assertTrue(should_limit)
should_not_limit = self.speed_limiter.should_limit_speed(5.0) # Below limit
self.assertFalse(should_not_limit)
def test_download_cache(self):
"""Test download caching mechanism."""
test_url = "http://example.com/video.mp4"
test_data = b"test video data"
# Test cache miss
cached_data = self.download_cache.get(test_url)
self.assertIsNone(cached_data)
# Test cache set and hit
self.download_cache.set(test_url, test_data)
cached_data = self.download_cache.get(test_url)
self.assertEqual(cached_data, test_data)
# Test cache invalidation
self.download_cache.invalidate(test_url)
cached_data = self.download_cache.get(test_url)
self.assertIsNone(cached_data)
def test_memory_monitor(self):
"""Test memory monitoring."""
monitor = MemoryMonitor(threshold_mb=100)
# Test memory usage calculation
usage_mb = monitor.get_current_memory_usage()
self.assertIsInstance(usage_mb, (int, float))
self.assertGreater(usage_mb, 0)
# Test threshold checking
is_high = monitor.is_memory_usage_high()
self.assertIsInstance(is_high, bool)
class TestAPIIntegration(unittest.TestCase):
"""Test cases for API integration components."""
def setUp(self):
"""Set up API components."""
self.webhook_manager = WebhookManager()
self.export_manager = ExportManager()
def test_webhook_manager(self):
"""Test webhook functionality."""
test_url = "https://example.com/webhook"
self.webhook_manager.add_webhook(test_url)
# Test webhook is registered
self.assertIn(test_url, self.webhook_manager.webhooks)
# Test webhook removal
self.webhook_manager.remove_webhook(test_url)
self.assertNotIn(test_url, self.webhook_manager.webhooks)
def test_export_manager(self):
"""Test data export functionality."""
# Mock series app
mock_series_app = Mock()
mock_series = Mock()
mock_series.name = "Test Anime"
mock_series.folder = "test_folder"
mock_series.missing = [1, 2, 3]
mock_series_app.series_list.series = [mock_series]
self.export_manager.series_app = mock_series_app
# Test JSON export
json_data = self.export_manager.export_to_json()
self.assertIsInstance(json_data, str)
# Parse and validate JSON
parsed_data = json.loads(json_data)
self.assertIn('anime_list', parsed_data)
self.assertEqual(len(parsed_data['anime_list']), 1)
self.assertEqual(parsed_data['anime_list'][0]['name'], "Test Anime")
# Test CSV export
csv_data = self.export_manager.export_to_csv()
self.assertIsInstance(csv_data, str)
self.assertIn("Test Anime", csv_data)
self.assertIn("test_folder", csv_data)
class TestBackupManager(unittest.TestCase):
"""Test cases for backup management."""
def setUp(self):
"""Set up test environment."""
self.temp_dir = tempfile.mkdtemp()
# Create test database
self.test_db = os.path.join(self.temp_dir, "test.db")
self.db_manager = DatabaseManager(self.test_db)
# Create backup manager
self.backup_manager = BackupManager(
self.db_manager,
os.path.join(self.temp_dir, "backups")
)
def tearDown(self):
"""Clean up test environment."""
self.db_manager.close()
shutil.rmtree(self.temp_dir, ignore_errors=True)
def test_create_backup(self):
"""Test backup creation."""
# Add some test data
anime = AnimeMetadata(
anime_id="backup-test",
name="Backup Test Anime",
folder="backup_test"
)
with self.db_manager.get_connection() as conn:
conn.execute("""
INSERT INTO anime_metadata
(anime_id, name, folder, created_at, last_updated)
VALUES (?, ?, ?, ?, ?)
""", (anime.anime_id, anime.name, anime.folder,
anime.created_at, anime.last_updated))
# Create backup
backup_info = self.backup_manager.create_full_backup("Test backup")
self.assertIsNotNone(backup_info)
self.assertTrue(os.path.exists(backup_info.backup_path))
self.assertGreater(backup_info.size_bytes, 0)
def test_restore_backup(self):
"""Test backup restoration."""
# Create initial data
anime_id = "restore-test"
with self.db_manager.get_connection() as conn:
conn.execute("""
INSERT INTO anime_metadata
(anime_id, name, folder, created_at, last_updated)
VALUES (?, ?, ?, ?, ?)
""", (anime_id, "Original", "original_folder",
datetime.utcnow(), datetime.utcnow()))
# Create backup
backup_info = self.backup_manager.create_full_backup("Pre-modification backup")
# Modify data
with self.db_manager.get_connection() as conn:
conn.execute("""
UPDATE anime_metadata SET name = ? WHERE anime_id = ?
""", ("Modified", anime_id))
# Restore backup
success = self.backup_manager.restore_backup(backup_info.backup_id)
self.assertTrue(success)
# Verify restoration
results = self.db_manager.execute_query(
"SELECT name FROM anime_metadata WHERE anime_id = ?",
(anime_id,)
)
self.assertEqual(len(results), 1)
self.assertEqual(results[0]['name'], "Original")
class TestConcurrency(unittest.TestCase):
"""Test cases for concurrent operations."""
def test_concurrent_downloads(self):
"""Test concurrent download handling."""
results = []
errors = []
def mock_download(episode_id):
"""Mock download function."""
try:
# Simulate download work
threading.Event().wait(0.1)
results.append(f"Downloaded {episode_id}")
return True
except Exception as e:
errors.append(str(e))
return False
# Create multiple download threads
threads = []
for i in range(5):
thread = threading.Thread(target=mock_download, args=(f"episode_{i}",))
threads.append(thread)
thread.start()
# Wait for all threads to complete
for thread in threads:
thread.join()
# Verify results
self.assertEqual(len(results), 5)
self.assertEqual(len(errors), 0)
def test_database_concurrent_access(self):
"""Test concurrent database access."""
# Create temporary database
temp_db = tempfile.NamedTemporaryFile(delete=False)
temp_db.close()
try:
db_manager = DatabaseManager(temp_db.name)
results = []
errors = []
def concurrent_insert(thread_id):
"""Concurrent database insert operation."""
try:
anime_id = f"concurrent-{thread_id}"
query = """
INSERT INTO anime_metadata
(anime_id, name, folder, created_at, last_updated)
VALUES (?, ?, ?, ?, ?)
"""
success = db_manager.execute_update(
query,
(anime_id, f"Anime {thread_id}", f"folder_{thread_id}",
datetime.utcnow(), datetime.utcnow())
)
if success:
results.append(thread_id)
except Exception as e:
errors.append(str(e))
# Create concurrent threads
threads = []
for i in range(10):
thread = threading.Thread(target=concurrent_insert, args=(i,))
threads.append(thread)
thread.start()
# Wait for completion
for thread in threads:
thread.join()
# Verify results
self.assertEqual(len(results), 10)
self.assertEqual(len(errors), 0)
# Verify database state
count_results = db_manager.execute_query(
"SELECT COUNT(*) as count FROM anime_metadata"
)
self.assertEqual(count_results[0]['count'], 10)
db_manager.close()
finally:
os.unlink(temp_db.name)
def run_test_suite():
"""Run the complete test suite."""
# Create test suite
suite = unittest.TestSuite()
# Add all test cases
test_classes = [
TestSerie,
TestSeriesList,
TestDatabaseManager,
TestErrorRecoveryManager,
TestPerformanceOptimizer,
TestAPIIntegration,
TestBackupManager,
TestConcurrency
]
for test_class in test_classes:
tests = unittest.TestLoader().loadTestsFromTestCase(test_class)
suite.addTests(tests)
# Run tests
runner = unittest.TextTestRunner(verbosity=2)
result = runner.run(suite)
return result
if __name__ == '__main__':
print("Running AniWorld Unit Tests...")
print("=" * 50)
result = run_test_suite()
print("\n" + "=" * 50)
print(f"Tests run: {result.testsRun}")
print(f"Failures: {len(result.failures)}")
print(f"Errors: {len(result.errors)}")
if result.failures:
print("\nFailures:")
for test, traceback in result.failures:
print(f"- {test}: {traceback}")
if result.errors:
print("\nErrors:")
for test, traceback in result.errors:
print(f"- {test}: {traceback}")
if result.wasSuccessful():
print("\nAll tests passed! ✅")
sys.exit(0)
else:
print("\nSome tests failed! ❌")
sys.exit(1)

View File

@@ -0,0 +1 @@
# Test package initialization

View File

@@ -0,0 +1,20 @@
@echo off
echo.
echo 🚀 AniWorld Core Functionality Tests
echo =====================================
echo.
cd /d "%~dp0"
python run_core_tests.py
if %ERRORLEVEL% EQU 0 (
echo.
echo ✅ All tests completed successfully!
) else (
echo.
echo ❌ Some tests failed. Check output above.
)
echo.
echo Press any key to continue...
pause > nul

View File

@@ -0,0 +1,57 @@
"""
Simple test runner for core AniWorld server functionality.
This script runs the essential tests to validate JavaScript/CSS generation.
"""
import unittest
import sys
import os
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
if __name__ == '__main__':
print("🚀 Running AniWorld Core Functionality Tests")
print("=" * 50)
# Import and run the core tests
from test_core_functionality import TestManagerGenerationCore, TestComprehensiveSuite
# Create test suite
suite = unittest.TestSuite()
# Add core manager tests
suite.addTest(TestManagerGenerationCore('test_keyboard_shortcut_manager_generation'))
suite.addTest(TestManagerGenerationCore('test_drag_drop_manager_generation'))
suite.addTest(TestManagerGenerationCore('test_accessibility_manager_generation'))
suite.addTest(TestManagerGenerationCore('test_user_preferences_manager_generation'))
suite.addTest(TestManagerGenerationCore('test_advanced_search_manager_generation'))
suite.addTest(TestManagerGenerationCore('test_undo_redo_manager_generation'))
suite.addTest(TestManagerGenerationCore('test_multi_screen_manager_generation'))
# Add comprehensive test
suite.addTest(TestComprehensiveSuite('test_all_manager_fixes_comprehensive'))
# Run tests
runner = unittest.TextTestRunner(verbosity=1, buffer=True)
result = runner.run(suite)
# Print summary
print("\n" + "=" * 50)
if result.wasSuccessful():
print("🎉 ALL CORE TESTS PASSED!")
print("✅ JavaScript/CSS generation working correctly")
print("✅ All manager classes validated")
print("✅ No syntax or runtime errors found")
else:
print("❌ Some core tests failed")
if result.failures:
for test, error in result.failures:
print(f" FAIL: {test}")
if result.errors:
for test, error in result.errors:
print(f" ERROR: {test}")
print("=" * 50)
sys.exit(0 if result.wasSuccessful() else 1)

View File

@@ -0,0 +1,10 @@
@echo off
echo Running AniWorld Server Test Suite...
echo.
cd /d "%~dp0"
python run_tests.py
echo.
echo Test run completed.
pause

108
tests/unit/web/run_tests.py Normal file
View File

@@ -0,0 +1,108 @@
"""
Test runner for the AniWorld server test suite.
This script runs all test modules and provides a comprehensive report.
"""
import unittest
import sys
import os
from io import StringIO
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
def run_all_tests():
"""Run all test modules and provide a summary report."""
print("=" * 60)
print("AniWorld Server Test Suite")
print("=" * 60)
# Discover and run all tests
loader = unittest.TestLoader()
test_dir = os.path.dirname(os.path.abspath(__file__))
# Load all test modules
suite = loader.discover(test_dir, pattern='test_*.py')
# Run tests with detailed output
stream = StringIO()
runner = unittest.TextTestRunner(
stream=stream,
verbosity=2,
buffer=True
)
result = runner.run(suite)
# Print results
output = stream.getvalue()
print(output)
# Summary
print("\n" + "=" * 60)
print("TEST SUMMARY")
print("=" * 60)
total_tests = result.testsRun
failures = len(result.failures)
errors = len(result.errors)
skipped = len(result.skipped) if hasattr(result, 'skipped') else 0
passed = total_tests - failures - errors - skipped
print(f"Total Tests Run: {total_tests}")
print(f"Passed: {passed}")
print(f"Failed: {failures}")
print(f"Errors: {errors}")
print(f"Skipped: {skipped}")
if result.wasSuccessful():
print("\n🎉 ALL TESTS PASSED! 🎉")
print("✅ No JavaScript or CSS generation issues found!")
print("✅ All manager classes working correctly!")
print("✅ Authentication system validated!")
return True
else:
print("\n❌ Some tests failed. Please check the output above.")
if result.failures:
print(f"\nFailures ({len(result.failures)}):")
for test, traceback in result.failures:
print(f" - {test}: {traceback.split(chr(10))[-2]}")
if result.errors:
print(f"\nErrors ({len(result.errors)}):")
for test, traceback in result.errors:
print(f" - {test}: {traceback.split(chr(10))[-2]}")
return False
def run_specific_test_module(module_name):
"""Run a specific test module."""
print(f"Running tests from module: {module_name}")
print("-" * 40)
loader = unittest.TestLoader()
suite = loader.loadTestsFromName(module_name)
runner = unittest.TextTestRunner(verbosity=2, buffer=True)
result = runner.run(suite)
return result.wasSuccessful()
if __name__ == '__main__':
if len(sys.argv) > 1:
# Run specific test module
module_name = sys.argv[1]
success = run_specific_test_module(module_name)
else:
# Run all tests
success = run_all_tests()
# Exit with appropriate code
sys.exit(0 if success else 1)

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env python3
"""
Test script to verify Flask app structure without initializing SeriesApp
"""
import sys
import os
# Test if we can import Flask modules
try:
from flask import Flask
from flask_socketio import SocketIO
print("✅ Flask and SocketIO imports successful")
except ImportError as e:
print(f"❌ Flask import failed: {e}")
sys.exit(1)
# Test if we can import our modules
try:
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..'))
from src.server.core.entities.series import Serie
from src.server.core.entities.SerieList import SerieList
print("✅ Core modules import successful")
except ImportError as e:
print(f"❌ Core module import failed: {e}")
sys.exit(1)
# Test Flask app creation
try:
app = Flask(__name__)
app.config['SECRET_KEY'] = 'test-key'
socketio = SocketIO(app, cors_allowed_origins="*")
print("✅ Flask app creation successful")
except Exception as e:
print(f"❌ Flask app creation failed: {e}")
sys.exit(1)
print("🎉 All tests passed! Flask app structure is valid.")
print("\nTo run the server:")
print("1. Set ANIME_DIRECTORY environment variable to your anime directory")
print("2. Run: python app.py")
print("3. Open browser to http://localhost:5000")

View File

@@ -0,0 +1,127 @@
"""
Test suite for authentication and session management.
This test module validates the authentication system, session management,
and security features.
"""
import unittest
import sys
import os
from unittest.mock import patch, MagicMock
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
class TestAuthenticationSystem(unittest.TestCase):
"""Test class for authentication and session management."""
def setUp(self):
"""Set up test fixtures before each test method."""
# Mock Flask app for testing
self.mock_app = MagicMock()
self.mock_app.config = {'SECRET_KEY': 'test_secret'}
def test_session_manager_initialization(self):
"""Test SessionManager initialization."""
try:
from auth import SessionManager
manager = SessionManager()
self.assertIsNotNone(manager)
self.assertTrue(hasattr(manager, 'login'))
self.assertTrue(hasattr(manager, 'check_password'))
print('✓ SessionManager initialization successful')
except Exception as e:
self.fail(f'SessionManager initialization failed: {e}')
def test_login_method_exists(self):
"""Test that login method exists and returns proper response."""
try:
from auth import SessionManager
manager = SessionManager()
# Test login method exists
self.assertTrue(hasattr(manager, 'login'))
# Test login with invalid credentials returns dict
result = manager.login('wrong_password')
self.assertIsInstance(result, dict)
self.assertIn('success', result)
self.assertFalse(result['success'])
print('✓ SessionManager login method validated')
except Exception as e:
self.fail(f'SessionManager login method test failed: {e}')
def test_password_checking(self):
"""Test password validation functionality."""
try:
from auth import SessionManager
manager = SessionManager()
# Test check_password method exists
self.assertTrue(hasattr(manager, 'check_password'))
# Test with empty/invalid password
result = manager.check_password('')
self.assertFalse(result)
result = manager.check_password('wrong_password')
self.assertFalse(result)
print('✓ SessionManager password checking validated')
except Exception as e:
self.fail(f'SessionManager password checking test failed: {e}')
class TestConfigurationSystem(unittest.TestCase):
"""Test class for configuration management."""
def test_config_manager_initialization(self):
"""Test ConfigManager initialization."""
try:
from config import ConfigManager
manager = ConfigManager()
self.assertIsNotNone(manager)
self.assertTrue(hasattr(manager, 'anime_directory'))
print('✓ ConfigManager initialization successful')
except Exception as e:
self.fail(f'ConfigManager initialization failed: {e}')
def test_anime_directory_property(self):
"""Test anime_directory property getter and setter."""
try:
from config import ConfigManager
manager = ConfigManager()
# Test getter
initial_dir = manager.anime_directory
self.assertIsInstance(initial_dir, str)
# Test setter exists
test_dir = 'C:\\TestAnimeDir'
manager.anime_directory = test_dir
# Verify setter worked
self.assertEqual(manager.anime_directory, test_dir)
print('✓ ConfigManager anime_directory property validated')
except Exception as e:
self.fail(f'ConfigManager anime_directory property test failed: {e}')
if __name__ == '__main__':
unittest.main(verbosity=2, buffer=True)

View File

@@ -0,0 +1,288 @@
"""
Focused test suite for manager JavaScript and CSS generation.
This test module validates the core functionality that we know is working.
"""
import unittest
import sys
import os
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
class TestManagerGenerationCore(unittest.TestCase):
"""Test class for validating core manager JavaScript/CSS generation functionality."""
def setUp(self):
"""Set up test fixtures before each test method."""
self.managers_tested = 0
self.total_js_chars = 0
self.total_css_chars = 0
print("\n" + "="*50)
def test_keyboard_shortcut_manager_generation(self):
"""Test KeyboardShortcutManager JavaScript generation."""
print("Testing KeyboardShortcutManager...")
try:
from keyboard_shortcuts import KeyboardShortcutManager
manager = KeyboardShortcutManager()
js = manager.get_shortcuts_js()
# Validate JS generation
self.assertIsInstance(js, str)
self.assertGreater(len(js), 1000) # Should be substantial
self.total_js_chars += len(js)
self.managers_tested += 1
print(f'✓ KeyboardShortcutManager: {len(js):,} JS characters generated')
except Exception as e:
self.fail(f'KeyboardShortcutManager test failed: {e}')
def test_drag_drop_manager_generation(self):
"""Test DragDropManager JavaScript and CSS generation."""
print("Testing DragDropManager...")
try:
from drag_drop import DragDropManager
manager = DragDropManager()
js = manager.get_drag_drop_js()
css = manager.get_css()
# Validate generation
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 1000)
self.assertGreater(len(css), 100)
# Check for proper JSON serialization (no Python booleans)
self.assertNotIn('True', js)
self.assertNotIn('False', js)
self.assertNotIn('None', js)
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ DragDropManager: {len(js):,} JS chars, {len(css):,} CSS chars')
except Exception as e:
self.fail(f'DragDropManager test failed: {e}')
def test_accessibility_manager_generation(self):
"""Test AccessibilityManager JavaScript and CSS generation."""
print("Testing AccessibilityManager...")
try:
from accessibility_features import AccessibilityManager
manager = AccessibilityManager()
js = manager.get_accessibility_js()
css = manager.get_css()
# Validate generation
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 1000)
self.assertGreater(len(css), 100)
# Check for proper JSON serialization
self.assertNotIn('True', js)
self.assertNotIn('False', js)
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ AccessibilityManager: {len(js):,} JS chars, {len(css):,} CSS chars')
except Exception as e:
self.fail(f'AccessibilityManager test failed: {e}')
def test_user_preferences_manager_generation(self):
"""Test UserPreferencesManager JavaScript and CSS generation."""
print("Testing UserPreferencesManager...")
try:
from user_preferences import UserPreferencesManager
manager = UserPreferencesManager()
# Verify preferences attribute exists (this was the main fix)
self.assertTrue(hasattr(manager, 'preferences'))
self.assertIsInstance(manager.preferences, dict)
js = manager.get_preferences_js()
css = manager.get_css()
# Validate generation
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 1000)
self.assertGreater(len(css), 100)
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ UserPreferencesManager: {len(js):,} JS chars, {len(css):,} CSS chars')
except Exception as e:
self.fail(f'UserPreferencesManager test failed: {e}')
def test_advanced_search_manager_generation(self):
"""Test AdvancedSearchManager JavaScript and CSS generation."""
print("Testing AdvancedSearchManager...")
try:
from advanced_search import AdvancedSearchManager
manager = AdvancedSearchManager()
js = manager.get_search_js()
css = manager.get_css()
# Validate generation
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 1000)
self.assertGreater(len(css), 100)
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ AdvancedSearchManager: {len(js):,} JS chars, {len(css):,} CSS chars')
except Exception as e:
self.fail(f'AdvancedSearchManager test failed: {e}')
def test_undo_redo_manager_generation(self):
"""Test UndoRedoManager JavaScript and CSS generation."""
print("Testing UndoRedoManager...")
try:
from undo_redo_manager import UndoRedoManager
manager = UndoRedoManager()
js = manager.get_undo_redo_js()
css = manager.get_css()
# Validate generation
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 1000)
self.assertGreater(len(css), 100)
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ UndoRedoManager: {len(js):,} JS chars, {len(css):,} CSS chars')
except Exception as e:
self.fail(f'UndoRedoManager test failed: {e}')
def test_multi_screen_manager_generation(self):
"""Test MultiScreenManager JavaScript and CSS generation."""
print("Testing MultiScreenManager...")
try:
from multi_screen_support import MultiScreenManager
manager = MultiScreenManager()
js = manager.get_multiscreen_js()
css = manager.get_multiscreen_css()
# Validate generation
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 1000)
self.assertGreater(len(css), 100)
# Check for proper f-string escaping (no Python syntax)
self.assertNotIn('True', js)
self.assertNotIn('False', js)
self.assertNotIn('None', js)
# Verify JavaScript is properly formatted
self.assertIn('class', js) # Should contain JavaScript class syntax
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ MultiScreenManager: {len(js):,} JS chars, {len(css):,} CSS chars')
except Exception as e:
self.fail(f'MultiScreenManager test failed: {e}')
class TestComprehensiveSuite(unittest.TestCase):
"""Comprehensive test to verify all fixes are working."""
def test_all_manager_fixes_comprehensive(self):
"""Run comprehensive test of all manager fixes."""
print("\n" + "="*60)
print("COMPREHENSIVE MANAGER VALIDATION")
print("="*60)
managers_tested = 0
total_js = 0
total_css = 0
# Test each manager
test_cases = [
('KeyboardShortcutManager', 'keyboard_shortcuts', 'get_shortcuts_js', None),
('DragDropManager', 'drag_drop', 'get_drag_drop_js', 'get_css'),
('AccessibilityManager', 'accessibility_features', 'get_accessibility_js', 'get_css'),
('UserPreferencesManager', 'user_preferences', 'get_preferences_js', 'get_css'),
('AdvancedSearchManager', 'advanced_search', 'get_search_js', 'get_css'),
('UndoRedoManager', 'undo_redo_manager', 'get_undo_redo_js', 'get_css'),
('MultiScreenManager', 'multi_screen_support', 'get_multiscreen_js', 'get_multiscreen_css'),
]
for class_name, module_name, js_method, css_method in test_cases:
try:
# Dynamic import
module = __import__(module_name, fromlist=[class_name])
manager_class = getattr(module, class_name)
manager = manager_class()
# Get JS
js_func = getattr(manager, js_method)
js = js_func()
self.assertIsInstance(js, str)
self.assertGreater(len(js), 0)
total_js += len(js)
# Get CSS if available
css_chars = 0
if css_method:
css_func = getattr(manager, css_method)
css = css_func()
self.assertIsInstance(css, str)
self.assertGreater(len(css), 0)
css_chars = len(css)
total_css += css_chars
managers_tested += 1
print(f'{class_name}: JS={len(js):,} chars' +
(f', CSS={css_chars:,} chars' if css_chars > 0 else ' (JS only)'))
except Exception as e:
self.fail(f'{class_name} failed: {e}')
# Final validation
expected_managers = 7
self.assertEqual(managers_tested, expected_managers)
self.assertGreater(total_js, 100000) # Should have substantial JS
self.assertGreater(total_css, 10000) # Should have substantial CSS
print(f'\n{"="*60}')
print(f'🎉 ALL {managers_tested} MANAGERS PASSED!')
print(f'📊 Total JavaScript: {total_js:,} characters')
print(f'🎨 Total CSS: {total_css:,} characters')
print(f'✅ No JavaScript or CSS generation issues found!')
print(f'{"="*60}')
if __name__ == '__main__':
# Run with high verbosity
unittest.main(verbosity=2, buffer=False)

View File

@@ -0,0 +1,131 @@
"""
Test suite for Flask application routes and API endpoints.
This test module validates the main Flask application functionality,
route handling, and API responses.
"""
import unittest
import sys
import os
from unittest.mock import patch, MagicMock
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
class TestFlaskApplication(unittest.TestCase):
"""Test class for Flask application and routes."""
def setUp(self):
"""Set up test fixtures before each test method."""
pass
def test_app_imports(self):
"""Test that main app module can be imported without errors."""
try:
import app
self.assertIsNotNone(app)
print('✓ Main app module imports successfully')
except Exception as e:
self.fail(f'App import failed: {e}')
@patch('app.Flask')
def test_app_initialization_components(self, mock_flask):
"""Test that app initialization components are available."""
try:
# Test manager imports
from keyboard_shortcuts import KeyboardShortcutManager
from drag_drop import DragDropManager
from accessibility_features import AccessibilityManager
from user_preferences import UserPreferencesManager
# Verify managers can be instantiated
keyboard_manager = KeyboardShortcutManager()
drag_manager = DragDropManager()
accessibility_manager = AccessibilityManager()
preferences_manager = UserPreferencesManager()
self.assertIsNotNone(keyboard_manager)
self.assertIsNotNone(drag_manager)
self.assertIsNotNone(accessibility_manager)
self.assertIsNotNone(preferences_manager)
print('✓ App manager components available')
except Exception as e:
self.fail(f'App component test failed: {e}')
class TestAPIEndpoints(unittest.TestCase):
"""Test class for API endpoint validation."""
def test_api_response_structure(self):
"""Test that API endpoints return proper JSON structure."""
try:
# Test that we can import the auth module for API responses
from auth import SessionManager
manager = SessionManager()
# Test login API response structure
response = manager.login('test_password')
self.assertIsInstance(response, dict)
self.assertIn('success', response)
print('✓ API response structure validated')
except Exception as e:
self.fail(f'API endpoint test failed: {e}')
class TestJavaScriptGeneration(unittest.TestCase):
"""Test class for dynamic JavaScript generation."""
def test_javascript_generation_no_syntax_errors(self):
"""Test that generated JavaScript doesn't contain Python syntax."""
try:
from multi_screen_support import MultiScreenSupportManager
manager = MultiScreenSupportManager()
js_code = manager.get_multiscreen_js()
# Check for Python-specific syntax that shouldn't be in JS
self.assertNotIn('True', js_code, 'JavaScript should use "true", not "True"')
self.assertNotIn('False', js_code, 'JavaScript should use "false", not "False"')
self.assertNotIn('None', js_code, 'JavaScript should use "null", not "None"')
# Check for proper JSON serialization indicators
self.assertIn('true', js_code.lower())
self.assertIn('false', js_code.lower())
print('✓ JavaScript generation syntax validated')
except Exception as e:
self.fail(f'JavaScript generation test failed: {e}')
def test_f_string_escaping(self):
"""Test that f-strings are properly escaped in JavaScript generation."""
try:
from multi_screen_support import MultiScreenSupportManager
manager = MultiScreenSupportManager()
js_code = manager.get_multiscreen_js()
# Ensure JavaScript object literals use proper syntax
# Look for proper JavaScript object/function syntax
self.assertGreater(len(js_code), 0)
# Check that braces are properly used (not bare Python f-string braces)
brace_count = js_code.count('{')
self.assertGreater(brace_count, 0)
print('✓ F-string escaping validated')
except Exception as e:
self.fail(f'F-string escaping test failed: {e}')
if __name__ == '__main__':
unittest.main(verbosity=2, buffer=True)

View File

@@ -0,0 +1,242 @@
"""
Test suite for manager JavaScript and CSS generation.
This test module validates that all manager classes can successfully generate
their JavaScript and CSS code without runtime errors.
"""
import unittest
import sys
import os
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
class TestManagerGeneration(unittest.TestCase):
"""Test class for validating manager JavaScript/CSS generation."""
def setUp(self):
"""Set up test fixtures before each test method."""
self.managers_tested = 0
self.total_js_chars = 0
self.total_css_chars = 0
def test_keyboard_shortcut_manager(self):
"""Test KeyboardShortcutManager JavaScript generation."""
try:
from keyboard_shortcuts import KeyboardShortcutManager
manager = KeyboardShortcutManager()
js = manager.get_shortcuts_js()
self.assertIsInstance(js, str)
self.assertGreater(len(js), 0)
self.total_js_chars += len(js)
self.managers_tested += 1
print(f'✓ KeyboardShortcutManager: JS={len(js)} chars (no CSS method)')
except Exception as e:
self.fail(f'KeyboardShortcutManager failed: {e}')
def test_drag_drop_manager(self):
"""Test DragDropManager JavaScript and CSS generation."""
try:
from drag_drop import DragDropManager
manager = DragDropManager()
js = manager.get_drag_drop_js()
css = manager.get_css()
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 0)
self.assertGreater(len(css), 0)
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ DragDropManager: JS={len(js)} chars, CSS={len(css)} chars')
except Exception as e:
self.fail(f'DragDropManager failed: {e}')
def test_accessibility_manager(self):
"""Test AccessibilityManager JavaScript and CSS generation."""
try:
from accessibility_features import AccessibilityManager
manager = AccessibilityManager()
js = manager.get_accessibility_js()
css = manager.get_css()
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 0)
self.assertGreater(len(css), 0)
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ AccessibilityManager: JS={len(js)} chars, CSS={len(css)} chars')
except Exception as e:
self.fail(f'AccessibilityManager failed: {e}')
def test_user_preferences_manager(self):
"""Test UserPreferencesManager JavaScript and CSS generation."""
try:
from user_preferences import UserPreferencesManager
manager = UserPreferencesManager()
js = manager.get_preferences_js()
css = manager.get_css()
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 0)
self.assertGreater(len(css), 0)
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ UserPreferencesManager: JS={len(js)} chars, CSS={len(css)} chars')
except Exception as e:
self.fail(f'UserPreferencesManager failed: {e}')
def test_advanced_search_manager(self):
"""Test AdvancedSearchManager JavaScript and CSS generation."""
try:
from advanced_search import AdvancedSearchManager
manager = AdvancedSearchManager()
js = manager.get_search_js()
css = manager.get_css()
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 0)
self.assertGreater(len(css), 0)
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ AdvancedSearchManager: JS={len(js)} chars, CSS={len(css)} chars')
except Exception as e:
self.fail(f'AdvancedSearchManager failed: {e}')
def test_undo_redo_manager(self):
"""Test UndoRedoManager JavaScript and CSS generation."""
try:
from undo_redo_manager import UndoRedoManager
manager = UndoRedoManager()
js = manager.get_undo_redo_js()
css = manager.get_css()
self.assertIsInstance(js, str)
self.assertIsInstance(css, str)
self.assertGreater(len(js), 0)
self.assertGreater(len(css), 0)
self.total_js_chars += len(js)
self.total_css_chars += len(css)
self.managers_tested += 1
print(f'✓ UndoRedoManager: JS={len(js)} chars, CSS={len(css)} chars')
except Exception as e:
self.fail(f'UndoRedoManager failed: {e}')
def test_all_managers_comprehensive(self):
"""Comprehensive test to ensure all managers work together."""
expected_managers = 6 # Total number of managers we expect to test
# Run all individual tests first
self.test_keyboard_shortcut_manager()
self.test_drag_drop_manager()
self.test_accessibility_manager()
self.test_user_preferences_manager()
self.test_advanced_search_manager()
self.test_undo_redo_manager()
# Validate overall results
self.assertEqual(self.managers_tested, expected_managers)
self.assertGreater(self.total_js_chars, 0)
self.assertGreater(self.total_css_chars, 0)
print(f'\n=== COMPREHENSIVE TEST SUMMARY ===')
print(f'Managers tested: {self.managers_tested}/{expected_managers}')
print(f'Total JavaScript generated: {self.total_js_chars:,} characters')
print(f'Total CSS generated: {self.total_css_chars:,} characters')
print('🎉 All manager JavaScript/CSS generation tests passed!')
def tearDown(self):
"""Clean up after each test method."""
pass
class TestManagerMethods(unittest.TestCase):
"""Test class for validating specific manager methods."""
def test_keyboard_shortcuts_methods(self):
"""Test that KeyboardShortcutManager has required methods."""
try:
from keyboard_shortcuts import KeyboardShortcutManager
manager = KeyboardShortcutManager()
# Test that required methods exist
self.assertTrue(hasattr(manager, 'get_shortcuts_js'))
self.assertTrue(hasattr(manager, 'setEnabled'))
self.assertTrue(hasattr(manager, 'updateShortcuts'))
# Test method calls
self.assertIsNotNone(manager.get_shortcuts_js())
print('✓ KeyboardShortcutManager methods validated')
except Exception as e:
self.fail(f'KeyboardShortcutManager method test failed: {e}')
def test_screen_reader_methods(self):
"""Test that ScreenReaderSupportManager has required methods."""
try:
from screen_reader_support import ScreenReaderManager
manager = ScreenReaderManager()
# Test that required methods exist
self.assertTrue(hasattr(manager, 'get_screen_reader_js'))
self.assertTrue(hasattr(manager, 'enhanceFormElements'))
self.assertTrue(hasattr(manager, 'generateId'))
print('✓ ScreenReaderSupportManager methods validated')
except Exception as e:
self.fail(f'ScreenReaderSupportManager method test failed: {e}')
def test_user_preferences_initialization(self):
"""Test that UserPreferencesManager initializes correctly."""
try:
from user_preferences import UserPreferencesManager
# Test initialization without Flask app
manager = UserPreferencesManager()
self.assertTrue(hasattr(manager, 'preferences'))
self.assertIsInstance(manager.preferences, dict)
self.assertGreater(len(manager.preferences), 0)
print('✓ UserPreferencesManager initialization validated')
except Exception as e:
self.fail(f'UserPreferencesManager initialization test failed: {e}')
if __name__ == '__main__':
# Configure test runner
unittest.main(verbosity=2, buffer=True)