""" Test HTML link interactivity when rendering pages. This test verifies that HTML links parsed via parse_html_string() are properly interactive and can be queried/detected when rendered on a page. """ import unittest from pyWebLayout.io.readers.html_extraction import parse_html_string from pyWebLayout.concrete.page import Page from pyWebLayout.style.page_style import PageStyle from pyWebLayout.abstract.inline import LinkedWord class TestHTMLLinkInteractivity(unittest.TestCase): """Test that HTML links are interactive when rendered.""" def test_simple_link_parsing(self): """Test that parse_html_string creates LinkedWord objects for links.""" html = '''

Click here to go back.

Or visit this setting.

''' blocks = parse_html_string(html) # Should have 2 paragraphs self.assertEqual(len(blocks), 2) # First paragraph - check for LinkedWord para1_words = list(blocks[0].words) linked_words_1 = [w for w in para1_words if isinstance(w, LinkedWord)] # "here" should be a LinkedWord self.assertEqual(len(linked_words_1), 1) self.assertEqual(linked_words_1[0].text, "here") self.assertEqual(linked_words_1[0].location, "action:back_to_library") # Second paragraph para2_words = list(blocks[1].words) linked_words_2 = [w for w in para2_words if isinstance(w, LinkedWord)] # "this" and "setting" should be LinkedWords self.assertEqual(len(linked_words_2), 2) link_texts = [w.text for w in linked_words_2] self.assertIn("this", link_texts) self.assertIn("setting", link_texts) def test_link_rendering_on_page(self): """Test that links are properly rendered and detectable on a page.""" from pyWebLayout.layout.document_layouter import DocumentLayouter html = '''

Settings

Font Size: - | +

Back to Library

''' blocks = parse_html_string(html) # Create a page and use DocumentLayouter to properly layout blocks page_style = PageStyle() page = Page((600, 800), page_style) layouter = DocumentLayouter(page) # Layout all blocks for block in blocks: layouter.layout_document([block]) # Render the page rendered_image = page.render() # Verify the page rendered self.assertIsNotNone(rendered_image) self.assertEqual(rendered_image.size, (600, 800)) # Now verify we can detect the links via query_point # We need to find the positions of the linked words found_links = [] # Scan the blocks for LinkedWords for block in blocks: if hasattr(block, 'words'): for word in block.words: if isinstance(word, LinkedWord): found_links.append({ 'text': word.text, 'location': word.location, 'link_type': word.link_type }) # Verify we found the expected links # -, +, Back, to, Library (5 LinkedWords total) self.assertGreater(len(found_links), 0, "Should find at least some LinkedWords") link_locations = [link['location'] for link in found_links] self.assertIn("setting:font_decrease", link_locations) self.assertIn("setting:font_increase", link_locations) self.assertIn("action:back_to_library", link_locations) def test_link_query_point_detection(self): """Test that query_point can detect links on a rendered page.""" from pyWebLayout.layout.document_layouter import DocumentLayouter html = '''

Click here to test.

''' blocks = parse_html_string(html) # Create a page page_style = PageStyle() page = Page((400, 200), page_style) layouter = DocumentLayouter(page) # Layout the block for block in blocks: layouter.layout_document([block]) # Get the rendered canvas _ = page.draw # Ensure canvas exists # Find the LinkedWord in the blocks link_word = None for block in blocks: if hasattr(block, 'words'): for word in block.words: if isinstance(word, LinkedWord) and word.location == "action:test": link_word = word break # Verify we found the link self.assertIsNotNone(link_word) self.assertEqual(link_word.text, "here") self.assertEqual(link_word.location, "action:test") # Test that query_point can detect the link # Try querying a point in the middle of the page where text should be # Note: The exact coordinates depend on the layout, but we can test the API result = page.query_point((100, 50)) if result: # If we hit something, verify we can access its properties self.assertIsNotNone(result.object_type) # Link detection would show is_interactive=True for links if result.is_interactive: self.assertIsNotNone(result.link_target) def test_settings_overlay_button_html(self): """Test the specific HTML pattern used for settings overlay buttons.""" # This is the pattern used in the settings overlay html = '''

Settings

◄ Back to Library

Font Size: 100%
[-] [+]

''' blocks = parse_html_string(html) # Find all LinkedWords 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) # Verify we found the expected links self.assertGreater(len(all_linked_words), 0, "Should find LinkedWords in settings HTML") # Check for specific link targets link_targets = {word.location for word in all_linked_words} self.assertIn("action:back_to_library", link_targets, "Should find 'Back to Library' link") self.assertIn("setting:font_decrease", link_targets, "Should find font decrease link") self.assertIn("setting:font_increase", link_targets, "Should find font increase link") # Verify the link texts back_to_library_words = [w for w in all_linked_words if w.location == "action:back_to_library"] self.assertGreater(len(back_to_library_words), 0, "Should have words linked to back_to_library action") # Print debug info print(f"\nFound {len(all_linked_words)} linked words:") for word in all_linked_words: print(f" - '{word.text}' -> {word.location}") if __name__ == '__main__': unittest.main()