227 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import pytest
 | |
| from unittest.mock import patch, MagicMock
 | |
| from models import db, ClassGroup
 | |
| from repositories.class_repository import ClassRepository
 | |
| 
 | |
| 
 | |
| class TestClassesRoutes:
 | |
|     """Tests for class management routes"""
 | |
| 
 | |
|     def test_classes_list_route(self, client, app):
 | |
|         """Test the classes listing route"""
 | |
|         with app.app_context():
 | |
|             # Create test data
 | |
|             class1 = ClassGroup(name="6A", year="2023-2024")
 | |
|             class2 = ClassGroup(name="5B", year="2023-2024")
 | |
|             db.session.add_all([class1, class2])
 | |
|             db.session.commit()
 | |
|             
 | |
|             response = client.get('/classes')
 | |
|             assert response.status_code == 200
 | |
|             assert b'6A' in response.data
 | |
|             assert b'5B' in response.data
 | |
| 
 | |
|     def test_classes_new_route(self, client, app):
 | |
|         """Test the new class form route"""
 | |
|         with app.app_context():
 | |
|             response = client.get('/classes/new')
 | |
|             assert response.status_code == 200
 | |
|             assert 'Créer une nouvelle classe'.encode('utf-8') in response.data
 | |
| 
 | |
|     def test_classes_create_valid_data(self, client, app):
 | |
|         """Test creating a class with valid data"""
 | |
|         with app.app_context():
 | |
|             data = {
 | |
|                 'name': '6A',
 | |
|                 'description': 'Classe de 6ème A',
 | |
|                 'year': '2023-2024',
 | |
|                 'csrf_token': 'dummy'  # CSRF disabled in tests
 | |
|             }
 | |
|             
 | |
|             with patch('routes.classes.ClassRepository') as mock_repo_class:
 | |
|                 mock_repo = MagicMock()
 | |
|                 mock_repo_class.return_value = mock_repo
 | |
|                 mock_repo.exists_by_name.return_value = False
 | |
|                 
 | |
|                 response = client.post('/classes/', data=data, follow_redirects=True)
 | |
|                 assert response.status_code == 200
 | |
|                 
 | |
|                 # Verify repository methods were called
 | |
|                 mock_repo.exists_by_name.assert_called_once_with('6A')
 | |
| 
 | |
|     def test_classes_create_duplicate_name(self, client, app):
 | |
|         """Test creating a class with existing name"""
 | |
|         with app.app_context():
 | |
|             data = {
 | |
|                 'name': '6A',
 | |
|                 'description': 'Classe de 6ème A',
 | |
|                 'year': '2023-2024',
 | |
|                 'csrf_token': 'dummy'
 | |
|             }
 | |
|             
 | |
|             with patch('routes.classes.ClassRepository') as mock_repo_class:
 | |
|                 mock_repo = MagicMock()
 | |
|                 mock_repo_class.return_value = mock_repo
 | |
|                 mock_repo.exists_by_name.return_value = True
 | |
|                 
 | |
|                 response = client.post('/classes/', data=data)
 | |
|                 assert response.status_code == 200
 | |
|                 assert 'Une classe avec ce nom existe déjà'.encode('utf-8') in response.data
 | |
| 
 | |
|     def test_classes_edit_route(self, client, app):
 | |
|         """Test the edit class form route"""
 | |
|         with app.app_context():
 | |
|             class_group = ClassGroup(name="6A", year="2023-2024")
 | |
|             db.session.add(class_group)
 | |
|             db.session.commit()
 | |
|             
 | |
|             with patch('routes.classes.ClassRepository') as mock_repo_class:
 | |
|                 mock_repo = MagicMock()
 | |
|                 mock_repo_class.return_value = mock_repo
 | |
|                 mock_repo.get_or_404.return_value = class_group
 | |
|                 
 | |
|                 response = client.get(f'/classes/{class_group.id}/edit')
 | |
|                 assert response.status_code == 200
 | |
|                 assert 'Modifier la classe'.encode('utf-8') in response.data
 | |
|                 
 | |
|                 mock_repo.get_or_404.assert_called_once_with(class_group.id)
 | |
| 
 | |
|     def test_classes_update_valid_data(self, client, app):
 | |
|         """Test updating a class with valid data"""
 | |
|         with app.app_context():
 | |
|             class_group = ClassGroup(name="6A", year="2023-2024")
 | |
|             db.session.add(class_group)
 | |
|             db.session.commit()
 | |
|             
 | |
|             data = {
 | |
|                 'name': '6A Modified',
 | |
|                 'description': 'Classe modifiée',
 | |
|                 'year': '2023-2024',
 | |
|                 'csrf_token': 'dummy'
 | |
|             }
 | |
|             
 | |
|             with patch('routes.classes.ClassRepository') as mock_repo_class:
 | |
|                 mock_repo = MagicMock()
 | |
|                 mock_repo_class.return_value = mock_repo
 | |
|                 mock_repo.get_or_404.return_value = class_group
 | |
|                 mock_repo.exists_by_name.return_value = False
 | |
|                 
 | |
|                 response = client.post(f'/classes/{class_group.id}', data=data, follow_redirects=True)
 | |
|                 assert response.status_code == 200
 | |
|                 
 | |
|                 # Verify repository methods were called
 | |
|                 mock_repo.get_or_404.assert_called_once_with(class_group.id)
 | |
|                 mock_repo.exists_by_name.assert_called_once_with('6A Modified', exclude_id=class_group.id)
 | |
| 
 | |
|     def test_classes_delete_with_dependencies(self, client, app):
 | |
|         """Test deleting a class with dependencies"""
 | |
|         with app.app_context():
 | |
|             class_group = ClassGroup(name="6A", year="2023-2024")
 | |
|             db.session.add(class_group)
 | |
|             db.session.commit()
 | |
|             
 | |
|             with patch('routes.classes.ClassRepository') as mock_repo_class:
 | |
|                 mock_repo = MagicMock()
 | |
|                 mock_repo_class.return_value = mock_repo
 | |
|                 mock_repo.get_or_404.return_value = class_group
 | |
|                 mock_repo.can_be_deleted.return_value = (False, {'students': 5, 'assessments': 3})
 | |
|                 
 | |
|                 response = client.post(f'/classes/{class_group.id}/delete', follow_redirects=True)
 | |
|                 assert response.status_code == 200
 | |
|                 assert 'Impossible de supprimer'.encode('utf-8') in response.data
 | |
|                 
 | |
|                 # Verify repository methods were called
 | |
|                 mock_repo.get_or_404.assert_called_once_with(class_group.id)
 | |
|                 mock_repo.can_be_deleted.assert_called_once_with(class_group.id)
 | |
| 
 | |
|     def test_classes_delete_success(self, client, app):
 | |
|         """Test successful deletion of a class"""
 | |
|         with app.app_context():
 | |
|             class_group = ClassGroup(name="6A", year="2023-2024")
 | |
|             db.session.add(class_group)
 | |
|             db.session.commit()
 | |
|             
 | |
|             with patch('routes.classes.ClassRepository') as mock_repo_class:
 | |
|                 mock_repo = MagicMock()
 | |
|                 mock_repo_class.return_value = mock_repo
 | |
|                 mock_repo.get_or_404.return_value = class_group
 | |
|                 mock_repo.can_be_deleted.return_value = (True, {'students': 0, 'assessments': 0})
 | |
|                 
 | |
|                 response = client.post(f'/classes/{class_group.id}/delete', follow_redirects=True)
 | |
|                 assert response.status_code == 200
 | |
|                 
 | |
|                 # Verify repository methods were called
 | |
|                 mock_repo.get_or_404.assert_called_once_with(class_group.id)
 | |
|                 mock_repo.can_be_deleted.assert_called_once_with(class_group.id)
 | |
| 
 | |
|     def test_classes_details_repository_usage(self, app):
 | |
|         """Test that the class details route uses ClassRepository correctly"""
 | |
|         with app.app_context():
 | |
|             class_group = ClassGroup(name="6A", year="2023-2024")
 | |
|             db.session.add(class_group)
 | |
|             db.session.commit()
 | |
|             
 | |
|             with patch('routes.classes.ClassRepository') as mock_repo_class:
 | |
|                 with patch('routes.classes.render_template') as mock_render:
 | |
|                     mock_repo = MagicMock()
 | |
|                     mock_repo_class.return_value = mock_repo
 | |
|                     mock_repo.find_with_full_details.return_value = class_group
 | |
|                     mock_render.return_value = "rendered template"
 | |
|                     
 | |
|                     from routes.classes import bp
 | |
|                     with app.test_client() as client:
 | |
|                         response = client.get(f'/classes/{class_group.id}/details')
 | |
|                         
 | |
|                     # Verify repository was used correctly
 | |
|                     mock_repo.find_with_full_details.assert_called_once_with(class_group.id)
 | |
| 
 | |
|     def test_classes_details_not_found_repository_usage(self, app):
 | |
|         """Test class details route with non-existent class uses repository correctly"""
 | |
|         with app.app_context():
 | |
|             with patch('routes.classes.ClassRepository') as mock_repo_class:
 | |
|                 with patch('flask.abort') as mock_abort:
 | |
|                     mock_repo = MagicMock()
 | |
|                     mock_repo_class.return_value = mock_repo
 | |
|                     mock_repo.find_with_full_details.return_value = None
 | |
|                     
 | |
|                     from routes.classes import bp
 | |
|                     with app.test_client() as client:
 | |
|                         try:
 | |
|                             client.get('/classes/999/details')
 | |
|                         except:
 | |
|                             pass  # abort() raises an exception
 | |
|                     
 | |
|                     # Verify repository was used and abort was called
 | |
|                     mock_repo.find_with_full_details.assert_called_once_with(999)
 | |
|                     mock_abort.assert_called_once_with(404)
 | |
| 
 | |
| 
 | |
| class TestMainClassesRoute:
 | |
|     """Tests for the main classes route in app.py"""
 | |
| 
 | |
|     def test_main_classes_route_with_repository(self, client, app):
 | |
|         """Test the main /classes route uses ClassRepository"""
 | |
|         with app.app_context():
 | |
|             # Create test data
 | |
|             class1 = ClassGroup(name="6A", year="2023-2024")
 | |
|             class2 = ClassGroup(name="5B", year="2023-2024")
 | |
|             db.session.add_all([class1, class2])
 | |
|             db.session.commit()
 | |
|             
 | |
|             # Test the actual implementation without mocking
 | |
|             response = client.get('/classes')
 | |
|             assert response.status_code == 200
 | |
|             assert b'6A' in response.data
 | |
|             assert b'5B' in response.data
 | |
| 
 | |
|     def test_main_classes_route_error_handling(self, client, app):
 | |
|         """Test error handling in main classes route"""
 | |
|         with app.app_context():
 | |
|             with patch('app.ClassRepository') as mock_repo_class:
 | |
|                 mock_repo = MagicMock()
 | |
|                 mock_repo_class.return_value = mock_repo
 | |
|                 mock_repo.find_all_ordered.side_effect = Exception("Database error")
 | |
|                 
 | |
|                 response = client.get('/classes')
 | |
|                 assert response.status_code == 500
 | |
|                 assert 'Erreur lors du chargement des classes'.encode('utf-8') in response.data |