First paragraph with bold text.
+Second paragraph with italic text.
+-
+
- Item 1 +
- Item 2 +
- Item 3 +
diff --git a/changedetectionio/tests/unit/test_html_to_text.py b/changedetectionio/tests/unit/test_html_to_text.py new file mode 100644 index 000000000..2fb769899 --- /dev/null +++ b/changedetectionio/tests/unit/test_html_to_text.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 +# coding=utf-8 + +"""Unit tests for html_tools.html_to_text function.""" + +import hashlib +import threading +from queue import Queue +import pytest + +from changedetectionio.html_tools import html_to_text + + +class TestHtmlToText: + """Test html_to_text function for correctness and thread-safety.""" + + def test_basic_text_extraction(self): + """Test basic HTML to text conversion.""" + html = '
Paragraph text.
' + text = html_to_text(html) + + assert 'Title' in text + assert 'Paragraph text.' in text + assert '<' not in text # HTML tags should be stripped + assert '>' not in text + + def test_empty_html(self): + """Test handling of empty HTML.""" + html = '' + text = html_to_text(html) + + # Should return empty or whitespace only + assert text.strip() == '' + + def test_nested_elements(self): + """Test extraction from nested HTML elements.""" + html = ''' + + +First paragraph
+Second paragraph
+Test & <special> characters
' + text = html_to_text(html) + + # Entities should be decoded + assert 'Test &' in text or 'Test &' in text + assert 'special' in text + + def test_whitespace_handling(self): + """Test that whitespace is properly handled.""" + html = 'Line 1
Line 2
' + text = html_to_text(html) + + # Should have some separation between lines + assert 'Line 1' in text + assert 'Line 2' in text + assert text.count('\n') >= 1 # At least one newline + + def test_deterministic_output(self): + """Test that the same HTML always produces the same text.""" + html = 'Content here
' + + # Extract text multiple times + results = [html_to_text(html) for _ in range(10)] + + # All results should be identical + assert len(set(results)) == 1, "html_to_text should be deterministic" + + def test_thread_safety_determinism(self): + """ + Test that html_to_text produces deterministic output under high concurrency. + + This is the critical test for the lxml threading bug fix. + Without the thread-local parser fix, this test would occasionally fail + under high concurrency when multiple threads share the global parser. + """ + html = ''' + +First paragraph with bold text.
+Second paragraph with italic text.
+