Improved handling of pagnination.
Python CI / test (push) Failing after 4m8s

This commit is contained in:
2025-06-08 13:29:44 +02:00
parent 80edfcca84
commit 8c35cbf5ce
10 changed files with 934 additions and 517 deletions
+1 -1
View File
@@ -287,7 +287,7 @@ class TestPage(unittest.TestCase):
self.assertEqual(page._mode, 'RGBA')
self.assertEqual(page._direction, 'vertical')
self.assertEqual(page._spacing, 10)
self.assertEqual(page._halign, Alignment.LEFT)
self.assertEqual(page._halign, Alignment.CENTER)
self.assertEqual(page._valign, Alignment.TOP)
def test_page_initialization_with_params(self):
+32 -135
View File
@@ -1,6 +1,6 @@
"""
Unit tests for pyWebLayout.concrete.text module.
Tests the Text, RenderableWord, and Line classes for text rendering functionality.
Tests the Text and Line classes for text rendering functionality.
"""
import unittest
@@ -8,7 +8,7 @@ import numpy as np
from PIL import Image, ImageFont
from unittest.mock import Mock, patch, MagicMock
from pyWebLayout.concrete.text import Text, RenderableWord, Line
from pyWebLayout.concrete.text import Text, Line
from pyWebLayout.abstract.inline import Word
from pyWebLayout.style import Font, FontStyle, FontWeight, TextDecoration
from pyWebLayout.style.layout import Alignment
@@ -175,135 +175,6 @@ class TestText(unittest.TestCase):
self.assertEqual(size, text.size)
class TestRenderableWord(unittest.TestCase):
"""Test cases for the RenderableWord class"""
def setUp(self):
"""Set up test fixtures"""
self.font = Font(
font_path=None, # Use default font
font_size=12,
colour=(0, 0, 0)
)
self.abstract_word = Word("testing", self.font)
def test_renderable_word_initialization(self):
"""Test basic RenderableWord initialization"""
renderable = RenderableWord(self.abstract_word)
self.assertEqual(renderable._word, self.abstract_word)
self.assertEqual(len(renderable._text_parts), 1)
self.assertEqual(renderable._text_parts[0].text, "testing")
np.testing.assert_array_equal(renderable._origin, np.array([0, 0]))
def test_word_property(self):
"""Test word property accessor"""
renderable = RenderableWord(self.abstract_word)
self.assertEqual(renderable.word, self.abstract_word)
def test_text_parts_property(self):
"""Test text_parts property"""
renderable = RenderableWord(self.abstract_word)
self.assertIsInstance(renderable.text_parts, list)
self.assertEqual(len(renderable.text_parts), 1)
self.assertIsInstance(renderable.text_parts[0], Text)
def test_size_properties(self):
"""Test width and height properties"""
renderable = RenderableWord(self.abstract_word)
self.assertGreater(renderable.width, 0)
self.assertGreater(renderable.height, 0)
self.assertEqual(renderable.width, renderable._size[0])
self.assertEqual(renderable.height, renderable._size[1])
def test_set_origin(self):
"""Test setting origin coordinates"""
renderable = RenderableWord(self.abstract_word)
renderable.set_origin(25, 30)
np.testing.assert_array_equal(renderable._origin, np.array([25, 30]))
# Check that text parts also have updated origins
self.assertEqual(renderable._text_parts[0]._origin[0], 25)
self.assertEqual(renderable._text_parts[0]._origin[1], 30)
@patch.object(Word, 'hyphenate')
def test_update_from_word_hyphenated(self, mock_hyphenate):
"""Test updating from hyphenated word"""
# Mock hyphenation
mock_hyphenate.return_value = True
self.abstract_word._hyphenated_parts = ["test-", "ing"]
renderable = RenderableWord(self.abstract_word)
renderable.update_from_word()
self.assertEqual(len(renderable._text_parts), 2)
self.assertEqual(renderable._text_parts[0].text, "test-")
self.assertEqual(renderable._text_parts[1].text, "ing")
def test_get_part_size(self):
"""Test getting size of specific text part"""
renderable = RenderableWord(self.abstract_word)
size = renderable.get_part_size(0)
self.assertIsInstance(size, tuple)
self.assertEqual(len(size), 2)
def test_get_part_size_invalid_index(self):
"""Test getting size with invalid index"""
renderable = RenderableWord(self.abstract_word)
with self.assertRaises(IndexError):
renderable.get_part_size(5)
def test_render_single_part(self):
"""Test rendering word with single part"""
renderable = RenderableWord(self.abstract_word)
result = renderable.render()
self.assertIsInstance(result, Image.Image)
self.assertGreater(result.width, 0)
self.assertGreater(result.height, 0)
@patch.object(Word, 'hyphenate')
def test_render_multiple_parts(self, mock_hyphenate):
"""Test rendering word with multiple parts"""
# Mock hyphenation
mock_hyphenate.return_value = True
self.abstract_word._hyphenated_parts = ["test-", "ing"]
renderable = RenderableWord(self.abstract_word)
renderable.update_from_word()
result = renderable.render()
self.assertIsInstance(result, Image.Image)
self.assertGreater(result.width, 0)
self.assertGreater(result.height, 0)
def test_in_object_inside(self):
"""Test in_object with point inside word"""
renderable = RenderableWord(self.abstract_word)
renderable.set_origin(10, 15)
# Point inside word bounds
point = np.array([15, 20])
# This test might fail if the actual size calculation differs
# We'll check that the method returns a boolean
result = renderable.in_object(point)
self.assertIsInstance(result, (bool, np.bool_))
def test_in_object_outside(self):
"""Test in_object with point outside word"""
renderable = RenderableWord(self.abstract_word)
renderable.set_origin(10, 15)
# Point clearly outside word bounds
point = np.array([1000, 1000])
self.assertFalse(renderable.in_object(point))
class TestLine(unittest.TestCase):
"""Test cases for the Line class"""
@@ -324,7 +195,7 @@ class TestLine(unittest.TestCase):
self.assertEqual(line._spacing, self.spacing)
self.assertEqual(line._font, self.font)
self.assertEqual(len(line._renderable_words), 0)
self.assertEqual(len(line._text_objects), 0) # Updated to _text_objects
self.assertEqual(line._current_width, 0)
self.assertIsNone(line._previous)
self.assertIsNone(line._next)
@@ -337,11 +208,20 @@ class TestLine(unittest.TestCase):
self.assertEqual(line._previous, previous_line)
def test_renderable_words_property(self):
"""Test renderable_words property"""
"""Test renderable_words property (compatibility)"""
line = Line(self.spacing, self.origin, self.size, self.font)
self.assertIsInstance(line.renderable_words, list)
self.assertEqual(len(line.renderable_words), 0)
# Test that it returns the same as text_objects
self.assertEqual(line.renderable_words, line.text_objects)
def test_text_objects_property(self):
"""Test text_objects property"""
line = Line(self.spacing, self.origin, self.size, self.font)
self.assertIsInstance(line.text_objects, list)
self.assertEqual(len(line.text_objects), 0)
def test_set_next(self):
"""Test setting next line"""
@@ -357,7 +237,7 @@ class TestLine(unittest.TestCase):
result = line.add_word("short")
self.assertIsNone(result) # Word fits, no overflow
self.assertEqual(len(line._renderable_words), 1)
self.assertEqual(len(line._text_objects), 1) # Updated to _text_objects
self.assertGreater(line._current_width, 0)
def test_add_word_overflow(self):
@@ -397,7 +277,7 @@ class TestLine(unittest.TestCase):
line.add_word("second")
line.add_word("third")
self.assertEqual(len(line._renderable_words), 3)
self.assertEqual(len(line._text_objects), 3) # Updated to _text_objects
self.assertGreater(line._current_width, 0)
def test_render_empty_line(self):
@@ -462,6 +342,23 @@ class TestLine(unittest.TestCase):
self.assertIsInstance(result, Image.Image)
self.assertEqual(result.size, tuple(self.size))
def test_text_objects_contain_text_instances(self):
"""Test that text_objects contain Text instances"""
line = Line(self.spacing, self.origin, self.size, self.font)
line.add_word("test")
self.assertEqual(len(line.text_objects), 1)
self.assertIsInstance(line.text_objects[0], Text)
self.assertEqual(line.text_objects[0].text, "test")
def test_text_objects_linked_to_line(self):
"""Test that Text objects are properly linked to the line"""
line = Line(self.spacing, self.origin, self.size, self.font)
line.add_word("test")
text_obj = line.text_objects[0]
self.assertEqual(text_obj.line, line)
if __name__ == '__main__':
+4 -4
View File
@@ -49,7 +49,7 @@ class TestLineSplittingBug(unittest.TestCase):
# Check that the first part was added to the line
self.assertEqual(len(line.renderable_words), 1)
first_word_text = line.renderable_words[0].word.text
first_word_text = line.renderable_words[0].text
self.assertEqual(first_word_text, "super-")
# The overflow should be just the next part, not all parts joined
@@ -75,7 +75,7 @@ class TestLineSplittingBug(unittest.TestCase):
# Check that the first part was added to the line
self.assertEqual(len(line.renderable_words), 1)
first_word_text = line.renderable_words[0].word.text
first_word_text = line.renderable_words[0].text
self.assertEqual(first_word_text, "very-")
# The overflow should be just the next part ("long"), not multiple parts joined
@@ -99,7 +99,7 @@ class TestLineSplittingBug(unittest.TestCase):
# Only the first word should be in the line
self.assertEqual(len(line.renderable_words), 1)
self.assertEqual(line.renderable_words[0].word.text, "short")
self.assertEqual(line.renderable_words[0].text, "short")
def demonstrate_bug():
@@ -123,7 +123,7 @@ def demonstrate_bug():
print(f"Original word: 'hyperlongexampleword'")
print(f"Hyphenated to: 'hyper-long-example-word'")
print(f"First part added to line: '{line.renderable_words[0].word.text if line.renderable_words else 'None'}'")
print(f"First part added to line: '{line.renderable_words[0].text if line.renderable_words else 'None'}'")
print(f"Overflow returned: '{overflow}'")
print()
print("PROBLEM: The overflow should be 'long-' (next part only)")