- 9 nouveaux fichiers de tests (persistance, translations, fiches, indices, IHH) - Enrichissement des tests existants (graph_utils, gitea, widgets, tickets) - 67→448 tests, tous passent Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
194 lines
6.6 KiB
Python
194 lines
6.6 KiB
Python
"""Tests unitaires pour le module utils.widgets.
|
|
|
|
Ces tests vérifient le fonctionnement des widgets HTML personnalisés.
|
|
"""
|
|
|
|
from unittest.mock import patch
|
|
|
|
from utils.widgets import html_expander
|
|
|
|
|
|
class TestHtmlExpander:
|
|
"""Tests pour la fonction html_expander."""
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
def test_expander_basic(self, mock_markdown, mock_st):
|
|
"""Test la création basique d'un expander."""
|
|
mock_markdown.markdown.return_value = "<p>Test content</p>"
|
|
|
|
html_expander("Test Title", "Test content")
|
|
|
|
# Vérifier que markdown.markdown a été appelé
|
|
mock_markdown.markdown.assert_called_once_with("Test content")
|
|
|
|
# Vérifier que st.markdown a été appelé
|
|
assert mock_st.markdown.called
|
|
call_args = mock_st.markdown.call_args
|
|
html_output = call_args[0][0]
|
|
|
|
assert "Test Title" in html_output
|
|
assert "<p>Test content</p>" in html_output
|
|
assert "<details" in html_output
|
|
assert "<summary" in html_output
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
def test_expander_open_by_default(self, mock_markdown, mock_st):
|
|
"""Test un expander ouvert par défaut."""
|
|
mock_markdown.markdown.return_value = "<p>Content</p>"
|
|
|
|
html_expander("Title", "Content", open_by_default=True)
|
|
|
|
call_args = mock_st.markdown.call_args
|
|
html_output = call_args[0][0]
|
|
|
|
assert 'open' in html_output
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
def test_expander_closed_by_default(self, mock_markdown, mock_st):
|
|
"""Test un expander fermé par défaut."""
|
|
mock_markdown.markdown.return_value = "<p>Content</p>"
|
|
|
|
html_expander("Title", "Content", open_by_default=False)
|
|
|
|
call_args = mock_st.markdown.call_args
|
|
html_output = call_args[0][0]
|
|
|
|
# 'open' ne doit pas être dans les attributs si fermé
|
|
# Note: vérifie la logique, pas juste la présence du mot 'open'
|
|
assert '<details id=' in html_output
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
def test_expander_with_css_classes(self, mock_markdown, mock_st):
|
|
"""Test avec des classes CSS personnalisées."""
|
|
mock_markdown.markdown.return_value = "<p>Content</p>"
|
|
|
|
html_expander(
|
|
"Title",
|
|
"Content",
|
|
details_class="custom-details",
|
|
summary_class="custom-summary"
|
|
)
|
|
|
|
call_args = mock_st.markdown.call_args
|
|
html_output = call_args[0][0]
|
|
|
|
assert 'class="custom-details"' in html_output
|
|
assert 'class="custom-summary"' in html_output
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
@patch('utils.widgets.logger')
|
|
def test_expander_markdown_import_error(self, mock_logger, mock_markdown, mock_st):
|
|
"""Test le fallback si markdown n'est pas disponible."""
|
|
# Simuler une ImportError
|
|
mock_markdown.markdown.side_effect = ImportError("Module not found")
|
|
|
|
html_expander("Title", "Test\ncontent")
|
|
|
|
# Vérifier que le logger a été appelé
|
|
mock_logger.warning.assert_called_once()
|
|
assert "markdown" in mock_logger.warning.call_args[0][0].lower()
|
|
|
|
# Vérifier que le fallback HTML a été utilisé
|
|
call_args = mock_st.markdown.call_args
|
|
html_output = call_args[0][0]
|
|
|
|
# Le contenu doit être échappé avec <br>
|
|
assert "Test<br>content" in html_output or "Test\ncontent" in html_output
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
@patch('utils.widgets.logger')
|
|
def test_expander_markdown_other_error(self, mock_logger, mock_markdown, _mock_st):
|
|
"""Test la gestion d'autres erreurs lors de la conversion markdown."""
|
|
# Simuler une autre exception
|
|
mock_markdown.markdown.side_effect = ValueError("Invalid markdown")
|
|
|
|
html_expander("Title", "Content")
|
|
|
|
# Vérifier que l'erreur a été loggée
|
|
mock_logger.error.assert_called_once()
|
|
assert "erreur" in mock_logger.error.call_args[0][0].lower()
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
def test_expander_unique_ids(self, mock_markdown, mock_st):
|
|
"""Test que chaque expander a un ID unique."""
|
|
mock_markdown.markdown.return_value = "<p>Content</p>"
|
|
|
|
# Créer deux expanders
|
|
html_expander("Title 1", "Content 1")
|
|
call_1 = mock_st.markdown.call_args[0][0]
|
|
|
|
html_expander("Title 2", "Content 2")
|
|
call_2 = mock_st.markdown.call_args[0][0]
|
|
|
|
# Extraire les IDs
|
|
import re
|
|
id_pattern = r'id="(expander_[a-f0-9]+)"'
|
|
id_1 = re.search(id_pattern, call_1).group(1)
|
|
id_2 = re.search(id_pattern, call_2).group(1)
|
|
|
|
# Les IDs doivent être différents
|
|
assert id_1 != id_2
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
def test_expander_unsafe_html_enabled(self, mock_markdown, mock_st):
|
|
"""Test que unsafe_allow_html est activé."""
|
|
mock_markdown.markdown.return_value = "<p>Content</p>"
|
|
|
|
html_expander("Title", "Content")
|
|
|
|
# Vérifier que unsafe_allow_html=True
|
|
call_kwargs = mock_st.markdown.call_args[1]
|
|
assert call_kwargs.get("unsafe_allow_html") is True
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
def test_expander_with_special_characters(self, mock_markdown, mock_st):
|
|
"""Test avec des caractères spéciaux dans le titre et le contenu."""
|
|
mock_markdown.markdown.return_value = "<p>Content <></p>"
|
|
|
|
html_expander("Title <>&", "Content <>&")
|
|
|
|
call_args = mock_st.markdown.call_args
|
|
html_output = call_args[0][0]
|
|
|
|
# Le titre doit être présent
|
|
assert "Title <>&" in html_output
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
def test_expander_empty_content(self, mock_markdown, mock_st):
|
|
"""Test avec un contenu vide."""
|
|
mock_markdown.markdown.return_value = ""
|
|
|
|
html_expander("Title", "")
|
|
|
|
# Ne doit pas crasher
|
|
assert mock_st.markdown.called
|
|
|
|
@patch('utils.widgets.st')
|
|
@patch('utils.widgets.markdown')
|
|
def test_expander_multiline_content(self, mock_markdown, mock_st):
|
|
"""Test avec du contenu multiligne."""
|
|
content = """
|
|
# Titre
|
|
Paragraphe 1
|
|
|
|
Paragraphe 2
|
|
"""
|
|
mock_markdown.markdown.return_value = "<h1>Titre</h1><p>Paragraphe 1</p><p>Paragraphe 2</p>"
|
|
|
|
html_expander("Title", content)
|
|
|
|
call_args = mock_st.markdown.call_args
|
|
html_output = call_args[0][0]
|
|
|
|
assert "<h1>Titre</h1>" in html_output
|