pyWebLayout/tests/layout/test_html_links_in_ereader.py
2025-11-12 12:03:27 +00:00

149 lines
5.4 KiB
Python

"""
End-to-end test for HTML links in EreaderLayoutManager.
This test mimics exactly what the dreader application does:
1. Load HTML with links via parse_html_string
2. Create an EreaderLayoutManager
3. Render a page
4. Query for interactive elements
This should reveal if links are actually interactive after full rendering.
"""
import unittest
from pyWebLayout.io.readers.html_extraction import parse_html_string
from pyWebLayout.layout.ereader_manager import EreaderLayoutManager
from pyWebLayout.abstract.inline import LinkedWord
from pyWebLayout.concrete.functional import LinkText
class TestHTMLLinksInEreader(unittest.TestCase):
"""Test HTML link interactivity in the full ereader pipeline."""
def test_settings_overlay_links_are_interactive(self):
"""Test that settings overlay HTML creates interactive links."""
# This is realistic settings overlay HTML
html = '''
<div>
<h2>Settings</h2>
<p>
<a href="action:back_to_library">Back to Library</a>
</p>
<p>
Font Size:
<a href="setting:font_decrease">[-]</a>
<a href="setting:font_increase">[+]</a>
</p>
</div>
'''
# Step 1: Parse HTML to blocks
blocks = parse_html_string(html)
# Verify LinkedWords were created
all_linked_words = []
for block in blocks:
if hasattr(block, 'words'):
for word in block.words:
if isinstance(word, LinkedWord):
all_linked_words.append(word)
self.assertGreater(
len(all_linked_words),
0,
"Should create LinkedWords from HTML")
print(f"\n Created {len(all_linked_words)} LinkedWords from HTML")
# Step 2: Create EreaderLayoutManager (like the dreader app does)
page_size = (400, 600)
manager = EreaderLayoutManager(
blocks=blocks,
page_size=page_size,
document_id="test_settings"
)
# Step 3: Get the rendered page
page = manager.get_current_page()
self.assertIsNotNone(page)
# Step 4: Render to image
rendered_image = page.render()
self.assertIsNotNone(rendered_image)
print(f" Rendered page: {rendered_image.size}")
# Step 5: Find all interactive elements by scanning the page
# This is the CRITICAL test - are there LinkText objects in the page?
interactive_elements = []
# Scan through all children of the page
if hasattr(page, '_children'):
for child in page._children:
# Check if child is a Line
if hasattr(child, '_text_objects'):
for text_obj in child._text_objects:
if isinstance(text_obj, LinkText):
interactive_elements.append({
'type': 'LinkText',
'text': text_obj._text,
'location': text_obj.link.location,
'is_interactive': hasattr(text_obj, 'execute')
})
print(f" Found {len(interactive_elements)} LinkText objects in rendered page")
for elem in interactive_elements:
print(f" - '{elem['text']}' -> {elem['location']}")
# THIS IS THE KEY ASSERTION
self.assertGreater(
len(interactive_elements),
0,
"Settings overlay should have interactive LinkText objects after rendering!")
# Verify the expected links are present
locations = {elem['location'] for elem in interactive_elements}
self.assertIn("action:back_to_library", locations,
"Should find 'Back to Library' link")
self.assertIn("setting:font_decrease", locations,
"Should find font decrease link")
self.assertIn("setting:font_increase", locations,
"Should find font increase link")
def test_query_point_detects_links(self):
"""Test that query_point can detect LinkText objects."""
html = '<p><a href="action:test">Click here</a> to test.</p>'
blocks = parse_html_string(html)
manager = EreaderLayoutManager(
blocks=blocks,
page_size=(400, 200),
document_id="test_query"
)
page = manager.get_current_page()
page.render()
# Try to query various points on the page
# We don't know exact coordinates, so scan a grid
found_link = False
for y in range(20, 100, 10):
for x in range(20, 380, 20):
result = page.query_point((x, y))
if result and result.is_interactive:
print(f"\n Found interactive element at ({x}, {y})")
print(f" Type: {result.object_type}")
print(f" Link target: {result.link_target}")
print(f" Text: {result.text}")
found_link = True
self.assertEqual(result.link_target, "action:test")
break
if found_link:
break
self.assertTrue(
found_link,
"Should be able to detect link via query_point somewhere on the page")
if __name__ == '__main__':
unittest.main()