353 lines
11 KiB
Python
353 lines
11 KiB
Python
"""
|
|
Unit tests for the highlight system.
|
|
|
|
Tests Highlight, HighlightColor, HighlightManager, and integration with query system.
|
|
"""
|
|
|
|
import unittest
|
|
import tempfile
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
from pyWebLayout.core.highlight import (
|
|
Highlight,
|
|
HighlightColor,
|
|
HighlightManager,
|
|
create_highlight_from_query_result
|
|
)
|
|
from pyWebLayout.core.query import QueryResult, SelectionRange
|
|
|
|
|
|
class TestHighlightColor(unittest.TestCase):
|
|
"""Test HighlightColor enum"""
|
|
|
|
def test_colors_defined(self):
|
|
"""Test all expected colors are defined"""
|
|
expected_colors = ['YELLOW', 'GREEN', 'BLUE', 'PINK', 'ORANGE', 'PURPLE', 'RED']
|
|
|
|
for color_name in expected_colors:
|
|
self.assertTrue(hasattr(HighlightColor, color_name))
|
|
color = getattr(HighlightColor, color_name)
|
|
self.assertIsInstance(color.value, tuple)
|
|
self.assertEqual(len(color.value), 4) # RGBA
|
|
|
|
def test_yellow_is_default(self):
|
|
"""Test yellow highlight color"""
|
|
yellow = HighlightColor.YELLOW.value
|
|
self.assertEqual(yellow, (255, 255, 0, 100))
|
|
|
|
|
|
class TestHighlight(unittest.TestCase):
|
|
"""Test Highlight dataclass"""
|
|
|
|
def test_init_basic(self):
|
|
"""Test basic Highlight creation"""
|
|
highlight = Highlight(
|
|
id="test-id",
|
|
bounds=[(10, 20, 50, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="Hello"
|
|
)
|
|
|
|
self.assertEqual(highlight.id, "test-id")
|
|
self.assertEqual(len(highlight.bounds), 1)
|
|
self.assertEqual(highlight.bounds[0], (10, 20, 50, 15))
|
|
self.assertEqual(highlight.color, (255, 255, 0, 100))
|
|
self.assertEqual(highlight.text, "Hello")
|
|
self.assertIsNone(highlight.note)
|
|
self.assertEqual(highlight.tags, [])
|
|
|
|
def test_init_with_metadata(self):
|
|
"""Test Highlight with full metadata"""
|
|
highlight = Highlight(
|
|
id="test-id",
|
|
bounds=[(10, 20, 50, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="Hello",
|
|
note="Important word",
|
|
tags=["important", "keyword"],
|
|
timestamp=1234567890.0,
|
|
start_word_index=5,
|
|
end_word_index=5
|
|
)
|
|
|
|
self.assertEqual(highlight.note, "Important word")
|
|
self.assertEqual(highlight.tags, ["important", "keyword"])
|
|
self.assertEqual(highlight.timestamp, 1234567890.0)
|
|
self.assertEqual(highlight.start_word_index, 5)
|
|
self.assertEqual(highlight.end_word_index, 5)
|
|
|
|
def test_to_dict(self):
|
|
"""Test Highlight serialization"""
|
|
highlight = Highlight(
|
|
id="test-id",
|
|
bounds=[(10, 20, 50, 15), (70, 20, 40, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="Hello world",
|
|
note="Test note",
|
|
tags=["test"],
|
|
timestamp=1234567890.0
|
|
)
|
|
|
|
data = highlight.to_dict()
|
|
|
|
self.assertEqual(data['id'], "test-id")
|
|
self.assertEqual(len(data['bounds']), 2)
|
|
self.assertEqual(data['bounds'][0], (10, 20, 50, 15))
|
|
self.assertEqual(data['color'], (255, 255, 0, 100))
|
|
self.assertEqual(data['text'], "Hello world")
|
|
self.assertEqual(data['note'], "Test note")
|
|
self.assertEqual(data['tags'], ["test"])
|
|
self.assertEqual(data['timestamp'], 1234567890.0)
|
|
|
|
def test_from_dict(self):
|
|
"""Test Highlight deserialization"""
|
|
data = {
|
|
'id': "test-id",
|
|
'bounds': [[10, 20, 50, 15], [70, 20, 40, 15]],
|
|
'color': [255, 255, 0, 100],
|
|
'text': "Hello world",
|
|
'note': "Test note",
|
|
'tags': ["test"],
|
|
'timestamp': 1234567890.0,
|
|
'start_word_index': 5,
|
|
'end_word_index': 6
|
|
}
|
|
|
|
highlight = Highlight.from_dict(data)
|
|
|
|
self.assertEqual(highlight.id, "test-id")
|
|
self.assertEqual(len(highlight.bounds), 2)
|
|
self.assertEqual(highlight.bounds[0], (10, 20, 50, 15))
|
|
self.assertEqual(highlight.color, (255, 255, 0, 100))
|
|
self.assertEqual(highlight.text, "Hello world")
|
|
self.assertEqual(highlight.note, "Test note")
|
|
self.assertEqual(highlight.tags, ["test"])
|
|
self.assertEqual(highlight.start_word_index, 5)
|
|
self.assertEqual(highlight.end_word_index, 6)
|
|
|
|
|
|
class TestHighlightManager(unittest.TestCase):
|
|
"""Test HighlightManager class"""
|
|
|
|
def setUp(self):
|
|
"""Create temporary directory for highlights"""
|
|
self.temp_dir = tempfile.mkdtemp()
|
|
self.manager = HighlightManager(
|
|
document_id="test-doc",
|
|
highlights_dir=self.temp_dir
|
|
)
|
|
|
|
def tearDown(self):
|
|
"""Clean up temporary directory"""
|
|
shutil.rmtree(self.temp_dir)
|
|
|
|
def test_init(self):
|
|
"""Test HighlightManager initialization"""
|
|
self.assertEqual(self.manager.document_id, "test-doc")
|
|
self.assertEqual(self.manager.highlights_dir, Path(self.temp_dir))
|
|
self.assertEqual(len(self.manager.highlights), 0)
|
|
|
|
def test_add_highlight(self):
|
|
"""Test adding a highlight"""
|
|
highlight = Highlight(
|
|
id="test-1",
|
|
bounds=[(10, 20, 50, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="Test"
|
|
)
|
|
|
|
self.manager.add_highlight(highlight)
|
|
|
|
self.assertEqual(len(self.manager.highlights), 1)
|
|
self.assertIn("test-1", self.manager.highlights)
|
|
self.assertEqual(self.manager.highlights["test-1"], highlight)
|
|
|
|
def test_remove_highlight(self):
|
|
"""Test removing a highlight"""
|
|
highlight = Highlight(
|
|
id="test-1",
|
|
bounds=[(10, 20, 50, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="Test"
|
|
)
|
|
|
|
self.manager.add_highlight(highlight)
|
|
self.assertEqual(len(self.manager.highlights), 1)
|
|
|
|
result = self.manager.remove_highlight("test-1")
|
|
self.assertTrue(result)
|
|
self.assertEqual(len(self.manager.highlights), 0)
|
|
|
|
def test_remove_nonexistent_highlight(self):
|
|
"""Test removing a highlight that doesn't exist"""
|
|
result = self.manager.remove_highlight("nonexistent")
|
|
self.assertFalse(result)
|
|
|
|
def test_get_highlight(self):
|
|
"""Test getting a highlight by ID"""
|
|
highlight = Highlight(
|
|
id="test-1",
|
|
bounds=[(10, 20, 50, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="Test"
|
|
)
|
|
|
|
self.manager.add_highlight(highlight)
|
|
retrieved = self.manager.get_highlight("test-1")
|
|
|
|
self.assertIsNotNone(retrieved)
|
|
self.assertEqual(retrieved.id, "test-1")
|
|
self.assertEqual(retrieved.text, "Test")
|
|
|
|
def test_list_highlights(self):
|
|
"""Test listing all highlights"""
|
|
highlight1 = Highlight(
|
|
id="test-1",
|
|
bounds=[(10, 20, 50, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="First"
|
|
)
|
|
highlight2 = Highlight(
|
|
id="test-2",
|
|
bounds=[(100, 20, 50, 15)],
|
|
color=(100, 255, 100, 100),
|
|
text="Second"
|
|
)
|
|
|
|
self.manager.add_highlight(highlight1)
|
|
self.manager.add_highlight(highlight2)
|
|
|
|
highlights = self.manager.list_highlights()
|
|
self.assertEqual(len(highlights), 2)
|
|
self.assertIn(highlight1, highlights)
|
|
self.assertIn(highlight2, highlights)
|
|
|
|
def test_clear_all(self):
|
|
"""Test clearing all highlights"""
|
|
highlight1 = Highlight(
|
|
id="test-1",
|
|
bounds=[(10, 20, 50, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="First"
|
|
)
|
|
highlight2 = Highlight(
|
|
id="test-2",
|
|
bounds=[(100, 20, 50, 15)],
|
|
color=(100, 255, 100, 100),
|
|
text="Second"
|
|
)
|
|
|
|
self.manager.add_highlight(highlight1)
|
|
self.manager.add_highlight(highlight2)
|
|
self.assertEqual(len(self.manager.highlights), 2)
|
|
|
|
self.manager.clear_all()
|
|
self.assertEqual(len(self.manager.highlights), 0)
|
|
|
|
def test_persistence(self):
|
|
"""Test that highlights are persisted to disk"""
|
|
highlight = Highlight(
|
|
id="test-1",
|
|
bounds=[(10, 20, 50, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="Persisted"
|
|
)
|
|
|
|
self.manager.add_highlight(highlight)
|
|
|
|
# Create new manager for same document
|
|
new_manager = HighlightManager(
|
|
document_id="test-doc",
|
|
highlights_dir=self.temp_dir
|
|
)
|
|
|
|
# Should load existing highlights
|
|
self.assertEqual(len(new_manager.highlights), 1)
|
|
self.assertIn("test-1", new_manager.highlights)
|
|
self.assertEqual(new_manager.highlights["test-1"].text, "Persisted")
|
|
|
|
def test_get_highlights_for_page(self):
|
|
"""Test filtering highlights by page bounds"""
|
|
# Highlight on page
|
|
highlight1 = Highlight(
|
|
id="test-1",
|
|
bounds=[(100, 100, 50, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="On page"
|
|
)
|
|
|
|
# Highlight off page
|
|
highlight2 = Highlight(
|
|
id="test-2",
|
|
bounds=[(1000, 1000, 50, 15)],
|
|
color=(255, 255, 0, 100),
|
|
text="Off page"
|
|
)
|
|
|
|
self.manager.add_highlight(highlight1)
|
|
self.manager.add_highlight(highlight2)
|
|
|
|
# Page bounds (0, 0, 800, 1000)
|
|
page_bounds = (0, 0, 800, 1000)
|
|
page_highlights = self.manager.get_highlights_for_page(page_bounds)
|
|
|
|
self.assertEqual(len(page_highlights), 1)
|
|
self.assertEqual(page_highlights[0].id, "test-1")
|
|
|
|
|
|
class TestCreateHighlightFromQueryResult(unittest.TestCase):
|
|
"""Test create_highlight_from_query_result function"""
|
|
|
|
def test_create_from_single_result(self):
|
|
"""Test creating highlight from single QueryResult"""
|
|
result = QueryResult(
|
|
object=object(),
|
|
object_type="text",
|
|
bounds=(10, 20, 50, 15),
|
|
text="Hello"
|
|
)
|
|
|
|
highlight = create_highlight_from_query_result(
|
|
result,
|
|
color=(255, 255, 0, 100),
|
|
note="Test note",
|
|
tags=["test"]
|
|
)
|
|
|
|
self.assertIsNotNone(highlight.id)
|
|
self.assertEqual(len(highlight.bounds), 1)
|
|
self.assertEqual(highlight.bounds[0], (10, 20, 50, 15))
|
|
self.assertEqual(highlight.color, (255, 255, 0, 100))
|
|
self.assertEqual(highlight.text, "Hello")
|
|
self.assertEqual(highlight.note, "Test note")
|
|
self.assertEqual(highlight.tags, ["test"])
|
|
self.assertIsNotNone(highlight.timestamp)
|
|
|
|
def test_create_from_selection_range(self):
|
|
"""Test creating highlight from SelectionRange"""
|
|
results = [
|
|
QueryResult(object(), "text", (10, 20, 30, 15), text="Hello"),
|
|
QueryResult(object(), "text", (45, 20, 35, 15), text="world")
|
|
]
|
|
|
|
sel_range = SelectionRange((10, 20), (80, 35), results)
|
|
|
|
highlight = create_highlight_from_query_result(
|
|
sel_range,
|
|
color=(100, 255, 100, 100),
|
|
note="Multi-word"
|
|
)
|
|
|
|
self.assertIsNotNone(highlight.id)
|
|
self.assertEqual(len(highlight.bounds), 2)
|
|
self.assertEqual(highlight.bounds[0], (10, 20, 30, 15))
|
|
self.assertEqual(highlight.bounds[1], (45, 20, 35, 15))
|
|
self.assertEqual(highlight.color, (100, 255, 100, 100))
|
|
self.assertEqual(highlight.text, "Hello world")
|
|
self.assertEqual(highlight.note, "Multi-word")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|