import pytest from models import db, CompetenceScaleValue, AppConfig, Competence from app_config import config_manager from datetime import datetime class TestConfigManager: """Tests pour le ConfigManager et la gestion de la configuration.""" def test_get_grading_types(self, app): """Test récupération des types de notation.""" with app.app_context(): grading_types = config_manager.get_grading_types() assert 'notes' in grading_types assert 'score' in grading_types assert grading_types['notes']['label'] == 'Notes numériques' assert grading_types['score']['max_value'] == 3 def test_get_special_values(self, app): """Test récupération des valeurs spéciales.""" with app.app_context(): special_values = config_manager.get_special_values() assert '.' in special_values assert 'd' in special_values assert 'a' in special_values assert special_values['.']['label'] == 'Pas de réponse' assert special_values['d']['counts'] == False assert special_values['a']['value'] == 0 def test_get_score_meanings(self, app): """Test récupération des significations des scores.""" with app.app_context(): score_meanings = config_manager.get_score_meanings() assert 0 in score_meanings assert 1 in score_meanings assert 2 in score_meanings assert 3 in score_meanings assert score_meanings[0]['label'] == 'Non acquis' assert score_meanings[3]['label'] == 'Expert' def test_validate_grade_value(self, app): """Test validation des valeurs de notation.""" with app.app_context(): # Notes valides assert config_manager.validate_grade_value('15.5', 'notes') == True assert config_manager.validate_grade_value('0', 'notes') == True assert config_manager.validate_grade_value('20', 'notes') == True # Scores valides assert config_manager.validate_grade_value('0', 'score') == True assert config_manager.validate_grade_value('1', 'score') == True assert config_manager.validate_grade_value('2', 'score') == True assert config_manager.validate_grade_value('3', 'score') == True # Valeurs spéciales valides assert config_manager.validate_grade_value('.', 'notes') == True assert config_manager.validate_grade_value('d', 'score') == True assert config_manager.validate_grade_value('a', 'notes') == True # Valeurs invalides assert config_manager.validate_grade_value('5', 'score') == False assert config_manager.validate_grade_value('-1', 'notes') == False assert config_manager.validate_grade_value('abc', 'notes') == False assert config_manager.validate_grade_value('1.5', 'score') == False def test_get_display_info(self, app): """Test informations d'affichage.""" with app.app_context(): # Valeur spéciale info = config_manager.get_display_info('.', 'notes') assert 'color' in info assert 'label' in info assert info['label'] == 'Pas de réponse' # Score avec signification info = config_manager.get_display_info('2', 'score') assert info['label'] == 'Acquis' # Note numérique info = config_manager.get_display_info('15.5', 'notes') assert info['label'] == '15.5' class TestCompetenceScaleValue: """Tests pour le modèle CompetenceScaleValue.""" def test_create_scale_value(self, app): """Test création d'une valeur d'échelle.""" with app.app_context(): scale_value = CompetenceScaleValue( value='test', label='Test Value', color='#ff0000', included_in_total=True ) db.session.add(scale_value) db.session.commit() # Vérifier que la valeur a été créée saved_value = CompetenceScaleValue.query.get('test') assert saved_value is not None assert saved_value.label == 'Test Value' assert saved_value.color == '#ff0000' assert saved_value.included_in_total == True def test_scale_value_primary_key(self, app): """Test que 'value' est bien la clé primaire.""" with app.app_context(): scale_value1 = CompetenceScaleValue( value='unique', label='First', color='#ff0000' ) scale_value2 = CompetenceScaleValue( value='unique', label='Second', color='#00ff00' ) db.session.add(scale_value1) db.session.commit() # Essayer d'ajouter une valeur avec la même clé primaire db.session.add(scale_value2) with pytest.raises(Exception): db.session.commit() def test_get_competence_scale_values(self, app): """Test récupération des valeurs d'échelle.""" with app.app_context(): # Nettoyer la table d'abord CompetenceScaleValue.query.delete() db.session.commit() # Ajouter quelques valeurs de test values = [ CompetenceScaleValue(value='0', label='Zéro', color='#ff0000'), CompetenceScaleValue(value='1', label='Un', color='#ffff00'), CompetenceScaleValue(value='2', label='Deux', color='#00ff00'), ] for value in values: db.session.add(value) db.session.commit() # Récupérer via config_manager scale_values = config_manager.get_competence_scale_values() # Les clés doivent être des strings assert '0' in scale_values assert '1' in scale_values assert '2' in scale_values assert scale_values['0']['label'] == 'Zéro' assert scale_values['1']['color'] == '#ffff00' class TestConfigOperations: """Tests pour les opérations CRUD sur la configuration.""" def test_add_scale_value(self, app): """Test ajout d'une valeur d'échelle.""" with app.app_context(): # Ajouter une nouvelle valeur success = config_manager.add_scale_value('X', 'Valeur X', '#123456', False) assert success == True # Vérifier qu'elle a été ajoutée scale_value = CompetenceScaleValue.query.get('X') assert scale_value is not None assert scale_value.label == 'Valeur X' assert scale_value.color == '#123456' assert scale_value.included_in_total == False def test_update_scale_value(self, app): """Test mise à jour d'une valeur d'échelle.""" with app.app_context(): # Créer une valeur scale_value = CompetenceScaleValue( value='update_test', label='Original', color='#000000', included_in_total=True ) db.session.add(scale_value) db.session.commit() # Mettre à jour success = config_manager.update_scale_value('update_test', 'Updated', '#ffffff', False) assert success == True # Vérifier la mise à jour updated_value = CompetenceScaleValue.query.get('update_test') assert updated_value.label == 'Updated' assert updated_value.color == '#ffffff' assert updated_value.included_in_total == False def test_update_nonexistent_scale_value(self, app): """Test mise à jour d'une valeur qui n'existe pas.""" with app.app_context(): success = config_manager.update_scale_value('nonexistent', 'Test', '#000000', True) assert success == False def test_delete_scale_value(self, app): """Test suppression d'une valeur d'échelle.""" with app.app_context(): # Créer une valeur scale_value = CompetenceScaleValue( value='delete_test', label='To Delete', color='#000000' ) db.session.add(scale_value) db.session.commit() # Vérifier qu'elle existe assert CompetenceScaleValue.query.get('delete_test') is not None # Supprimer success = config_manager.delete_scale_value('delete_test') assert success == True # Vérifier qu'elle a été supprimée assert CompetenceScaleValue.query.get('delete_test') is None def test_delete_nonexistent_scale_value(self, app): """Test suppression d'une valeur qui n'existe pas.""" with app.app_context(): success = config_manager.delete_scale_value('nonexistent') assert success == False class TestConfigIntegration: """Tests d'intégration pour le système de configuration.""" @pytest.fixture def setup_scale_values(self, app): """Fixture pour créer des valeurs d'échelle de test.""" with app.app_context(): # Nettoyer d'abord les valeurs existantes pour éviter les contraintes UNIQUE CompetenceScaleValue.query.delete() db.session.commit() values = [ CompetenceScaleValue(value='0', label='Non acquis', color='#ef4444', included_in_total=True), CompetenceScaleValue(value='1', label='En cours', color='#f59e0b', included_in_total=True), CompetenceScaleValue(value='2', label='Acquis', color='#22c55e', included_in_total=True), CompetenceScaleValue(value='3', label='Expert', color='#3b82f6', included_in_total=True), CompetenceScaleValue(value='.', label='Pas de réponse', color='#6b7280', included_in_total=True), CompetenceScaleValue(value='d', label='Dispensé', color='#9ca3af', included_in_total=False), CompetenceScaleValue(value='a', label='Absent', color='#f87171', included_in_total=True), ] for value in values: db.session.add(value) db.session.commit() return values def test_full_scale_workflow(self, app, setup_scale_values): """Test workflow complet de gestion d'échelle.""" with app.app_context(): # 1. Récupérer les valeurs scale_values = config_manager.get_competence_scale_values() assert len(scale_values) == 7 # 2. Ajouter une nouvelle valeur success = config_manager.add_scale_value('N', 'Non évalué', '#cccccc', False) assert success == True scale_values = config_manager.get_competence_scale_values() assert len(scale_values) == 8 assert 'N' in scale_values # 3. Modifier une valeur existante success = config_manager.update_scale_value('N', 'Non évalué (modifié)', '#dddddd', True) assert success == True updated_value = CompetenceScaleValue.query.get('N') assert updated_value.label == 'Non évalué (modifié)' assert updated_value.included_in_total == True # 4. Supprimer la valeur success = config_manager.delete_scale_value('N') assert success == True scale_values = config_manager.get_competence_scale_values() assert len(scale_values) == 7 assert 'N' not in scale_values def test_validation_with_database_values(self, app, setup_scale_values): """Test validation avec les valeurs de la base de données.""" with app.app_context(): # Valeurs numériques des scores assert config_manager.validate_grade_value('0', 'score') == True assert config_manager.validate_grade_value('3', 'score') == True assert config_manager.validate_grade_value('4', 'score') == False # Au-dessus du max # Valeurs spéciales assert config_manager.validate_grade_value('.', 'notes') == True assert config_manager.validate_grade_value('d', 'score') == True assert config_manager.validate_grade_value('a', 'notes') == True # Valeurs inexistantes assert config_manager.validate_grade_value('Z', 'score') == False def test_display_info_with_database_values(self, app, setup_scale_values): """Test informations d'affichage avec valeurs de la base.""" with app.app_context(): # Score avec signification info = config_manager.get_display_info('2', 'score') assert info['label'] == 'Acquis' assert info['color'] == '#22c55e' # Valeur spéciale info = config_manager.get_display_info('.', 'notes') assert info['label'] == 'Pas de réponse' assert info['color'] == '#6b7280' # Valeur inexistante (devrait retourner la valeur par défaut) info = config_manager.get_display_info('99', 'notes') assert info['label'] == '99' # Valeur brute assert info['color'] == '#374151' # Couleur par défaut class TestConfigErrorHandling: """Tests de gestion d'erreurs pour la configuration.""" def test_add_duplicate_scale_value(self, app): """Test ajout d'une valeur d'échelle en double.""" with app.app_context(): # Ajouter une valeur success1 = config_manager.add_scale_value('dup', 'Original', '#000000') assert success1 == True # Essayer d'ajouter la même valeur success2 = config_manager.add_scale_value('dup', 'Duplicate', '#ffffff') assert success2 == False def test_invalid_color_format(self, app): """Test avec format de couleur invalide.""" with app.app_context(): # Ces tests dépendent de la validation dans les routes, # mais on peut tester le comportement du modèle scale_value = CompetenceScaleValue( value='invalid_color', label='Test', color='invalid' # Format invalide mais le modèle l'accepte ) db.session.add(scale_value) db.session.commit() # Le modèle accepte n'importe quelle string, la validation doit être faite côté route saved_value = CompetenceScaleValue.query.get('invalid_color') assert saved_value.color == 'invalid' def test_empty_label(self, app): """Test avec libellé vide.""" with app.app_context(): scale_value = CompetenceScaleValue( value='empty_label', label='', # Libellé vide color='#000000' ) db.session.add(scale_value) db.session.commit() saved_value = CompetenceScaleValue.query.get('empty_label') assert saved_value.label == ''