261 lines
11 KiB
Python
261 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Unit tests for the alignment handler system.
|
|
Tests the various alignment handlers (Left, Center, Right, Justify) and their integration with Line objects.
|
|
"""
|
|
|
|
import unittest
|
|
import numpy as np
|
|
from unittest.mock import Mock
|
|
|
|
from pyWebLayout.concrete.text import Line, Text, LeftAlignmentHandler, CenterRightAlignmentHandler, JustifyAlignmentHandler
|
|
from pyWebLayout.style import Alignment
|
|
from pyWebLayout.style import Font
|
|
from pyWebLayout.abstract import Word
|
|
from PIL import Image, ImageFont, ImageDraw
|
|
|
|
class TestAlignmentHandlers(unittest.TestCase):
|
|
"""Test cases for the alignment handler system"""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures"""
|
|
self.font = Font()
|
|
self.test_words = [Word(text, self.font) for text in ["This", "is", "a", "test", "sentence"]]
|
|
self.line_width = 300
|
|
self.line_height = 30
|
|
self.spacing = (5, 20) # min_spacing, max_spacing
|
|
self.origin = (0, 0)
|
|
self.size = (self.line_width, self.line_height)
|
|
|
|
# Create a real PIL image (canvas) for testing
|
|
self.canvas = Image.new('RGB', (800, 600), color='white')
|
|
|
|
# Create a real ImageDraw object
|
|
self.draw = ImageDraw.Draw(self.canvas)
|
|
|
|
# Create a real Font object
|
|
self.style = Font()
|
|
|
|
|
|
def test_left_alignment_handler_assignment(self):
|
|
"""Test that Line correctly assigns LeftAlignmentHandler for LEFT alignment"""
|
|
left_line = Line(self.spacing, self.origin, self.size, self.draw, font=self.style, halign=Alignment.LEFT)
|
|
|
|
self.assertIsInstance(left_line._alignment_handler, LeftAlignmentHandler)
|
|
|
|
def test_center_alignment_handler_assignment(self):
|
|
"""Test that Line correctly assigns CenterRightAlignmentHandler for CENTER alignment"""
|
|
center_line = Line(self.spacing, self.origin, self.size, self.draw, font=self.style, halign=Alignment.CENTER)
|
|
|
|
self.assertIsInstance(center_line._alignment_handler, CenterRightAlignmentHandler)
|
|
# Check that it's configured for CENTER alignment
|
|
self.assertEqual(center_line._alignment_handler._alignment, Alignment.CENTER)
|
|
|
|
def test_right_alignment_handler_assignment(self):
|
|
"""Test that Line correctly assigns CenterRightAlignmentHandler for RIGHT alignment"""
|
|
right_line = Line(self.spacing, self.origin, self.size, self.draw, font=self.style, halign=Alignment.RIGHT)
|
|
|
|
self.assertIsInstance(right_line._alignment_handler, CenterRightAlignmentHandler)
|
|
# Check that it's configured for RIGHT alignment
|
|
self.assertEqual(right_line._alignment_handler._alignment, Alignment.RIGHT)
|
|
|
|
def test_justify_alignment_handler_assignment(self):
|
|
"""Test that Line correctly assigns JustifyAlignmentHandler for JUSTIFY alignment"""
|
|
justify_line = Line(self.spacing, self.origin, self.size, self.draw, font=self.style, halign=Alignment.JUSTIFY)
|
|
|
|
self.assertIsInstance(justify_line._alignment_handler, JustifyAlignmentHandler)
|
|
|
|
def test_left_alignment_word_addition(self):
|
|
"""Test adding words to a left-aligned line"""
|
|
left_line = Line(self.spacing, self.origin, self.size, self.draw, halign=Alignment.LEFT)
|
|
|
|
# Add words until line is full or we run out
|
|
words_added = 0
|
|
for word in self.test_words:
|
|
result, part = left_line.add_word(word)
|
|
if not result:
|
|
# Word didn't fit
|
|
break
|
|
else:
|
|
words_added += 1
|
|
|
|
# Should have added at least some words
|
|
self.assertGreater(words_added, 0)
|
|
self.assertEqual(len(left_line.text_objects), words_added)
|
|
|
|
def test_center_alignment_word_addition(self):
|
|
"""Test adding words to a center-aligned line"""
|
|
center_line = Line(self.spacing, self.origin, self.size, self.draw, font=self.style, halign=Alignment.CENTER)
|
|
|
|
# Add words until line is full or we run out
|
|
words_added = 0
|
|
for word in self.test_words:
|
|
result, part = center_line.add_word(word)
|
|
if not result:
|
|
# Word didn't fit
|
|
break
|
|
else:
|
|
words_added += 1
|
|
|
|
# Should have added at least some words
|
|
self.assertGreater(words_added, 0)
|
|
self.assertEqual(len(center_line.text_objects), words_added)
|
|
|
|
def test_right_alignment_word_addition(self):
|
|
"""Test adding words to a right-aligned line"""
|
|
right_line = Line(self.spacing, self.origin, self.size, self.draw, font=self.style, halign=Alignment.RIGHT)
|
|
|
|
# Add words until line is full or we run out
|
|
words_added = 0
|
|
for word in self.test_words:
|
|
result, part = right_line.add_word(word)
|
|
if not result:
|
|
# Word didn't fit
|
|
break
|
|
else:
|
|
words_added += 1
|
|
|
|
# Should have added at least some words
|
|
self.assertGreater(words_added, 0)
|
|
self.assertEqual(len(right_line.text_objects), words_added)
|
|
|
|
def test_justify_alignment_word_addition(self):
|
|
"""Test adding words to a justified line"""
|
|
justify_line = Line(self.spacing, self.origin, self.size, self.draw, font=self.style, halign=Alignment.JUSTIFY)
|
|
|
|
# Add words until line is full or we run out
|
|
words_added = 0
|
|
for word in self.test_words:
|
|
result, part = justify_line.add_word(word)
|
|
if not result:
|
|
# Word didn't fit
|
|
break
|
|
else:
|
|
words_added += 1
|
|
|
|
# Should have added at least some words
|
|
self.assertGreater(words_added, 0)
|
|
self.assertEqual(len(justify_line.text_objects), words_added)
|
|
|
|
def test_handler_spacing_and_position_calculations(self):
|
|
"""Test spacing and position calculations for different alignment handlers"""
|
|
# Create sample text objects
|
|
text_objects = [Text(word, self.style, self.draw) for word in ["Hello", "World"]]
|
|
|
|
# Test each handler type
|
|
handlers = [
|
|
("Left", LeftAlignmentHandler()),
|
|
("Center", CenterRightAlignmentHandler(Alignment.CENTER)),
|
|
("Right", CenterRightAlignmentHandler(Alignment.RIGHT)),
|
|
("Justify", JustifyAlignmentHandler())
|
|
]
|
|
|
|
for name, handler in handlers:
|
|
with self.subTest(handler=name):
|
|
spacing_calc, position, overflow = handler.calculate_spacing_and_position(
|
|
text_objects, self.line_width, self.spacing[0], self.spacing[1])
|
|
|
|
# Check that spacing is a valid number
|
|
self.assertIsInstance(spacing_calc, (int, float))
|
|
self.assertGreaterEqual(spacing_calc, 0)
|
|
|
|
# Check that position is a valid number
|
|
self.assertIsInstance(position, (int, float))
|
|
self.assertGreaterEqual(position, 0)
|
|
|
|
# Check that overflow is a boolean
|
|
self.assertIsInstance(overflow, bool)
|
|
|
|
# Position should be within line width (unless overflow)
|
|
if not overflow:
|
|
self.assertLessEqual(position, self.line_width)
|
|
|
|
def test_left_handler_spacing_calculation(self):
|
|
"""Test specific spacing calculation for left alignment"""
|
|
handler = LeftAlignmentHandler()
|
|
text_objects = [Text(word, self.style, self.draw) for word in ["Hello", "World"]]
|
|
|
|
spacing_calc, position, overflow = handler.calculate_spacing_and_position(
|
|
text_objects, self.line_width, self.spacing[0], self.spacing[1])
|
|
|
|
# Left alignment should have position at 0
|
|
self.assertEqual(position, 0)
|
|
|
|
# Should not overflow with reasonable text
|
|
self.assertFalse(overflow)
|
|
|
|
def test_center_handler_spacing_calculation(self):
|
|
"""Test specific spacing calculation for center alignment"""
|
|
handler = CenterRightAlignmentHandler(Alignment.CENTER)
|
|
text_objects = [Text(word, self.style, self.draw) for word in ["Hello", "World"]]
|
|
|
|
spacing_calc, position, overflow = handler.calculate_spacing_and_position(
|
|
text_objects, self.line_width, self.spacing[0], self.spacing[1])
|
|
|
|
# Center alignment should have position > 0 (centered) if no overflow
|
|
if not overflow:
|
|
self.assertGreaterEqual(position, 0)
|
|
|
|
def test_right_handler_spacing_calculation(self):
|
|
"""Test specific spacing calculation for right alignment"""
|
|
handler = CenterRightAlignmentHandler(Alignment.RIGHT)
|
|
text_objects = [Text(word, self.style, self.draw) for word in ["Hello", "World"]]
|
|
|
|
spacing_calc, position, overflow = handler.calculate_spacing_and_position(
|
|
text_objects, self.line_width, self.spacing[0], self.spacing[1])
|
|
|
|
# Right alignment should have position >= 0
|
|
self.assertGreaterEqual(position, 0)
|
|
|
|
def test_justify_handler_spacing_calculation(self):
|
|
"""Test specific spacing calculation for justify alignment"""
|
|
handler = JustifyAlignmentHandler()
|
|
text_objects = [Text(word, self.style, self.draw) for word in ["Hello", "World"]]
|
|
|
|
spacing_calc, position, overflow = handler.calculate_spacing_and_position(
|
|
text_objects, self.line_width, self.spacing[0], self.spacing[1])
|
|
|
|
# Justify alignment should have position at 0
|
|
self.assertEqual(position, 0)
|
|
|
|
# Check spacing is reasonable
|
|
self.assertGreaterEqual(spacing_calc, 0)
|
|
|
|
def test_empty_line_alignment_handlers(self):
|
|
"""Test alignment handlers with empty lines"""
|
|
alignments = [Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.JUSTIFY]
|
|
|
|
for alignment in alignments:
|
|
with self.subTest(alignment=alignment):
|
|
line = Line(self.spacing, self.origin, self.size, self.draw, font=self.style, halign=alignment)
|
|
|
|
# Empty line should still have a handler
|
|
self.assertIsNotNone(line._alignment_handler)
|
|
|
|
# Should be able to render empty line
|
|
line.render()
|
|
|
|
def test_single_word_line_alignment(self):
|
|
"""Test alignment handlers with single word lines"""
|
|
alignments = [Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.JUSTIFY]
|
|
|
|
for alignment in alignments:
|
|
with self.subTest(alignment=alignment):
|
|
line = Line(self.spacing, self.origin, self.size, self.draw, font=self.style, halign=alignment)
|
|
|
|
# Create a test word
|
|
test_word = Word("test", self.style)
|
|
|
|
# Add a single word
|
|
result, part = line.add_word(test_word)
|
|
self.assertTrue(result) # Should fit
|
|
self.assertIsNone(part) # No overflow part
|
|
|
|
# Should be able to render single word line
|
|
line.render()
|
|
self.assertEqual(len(line.text_objects), 1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|