258 lines
8.7 KiB
Python
258 lines
8.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Unit tests for paragraph layout fixes.
|
|
Tests the paragraph layout system and page rendering functionality.
|
|
"""
|
|
|
|
import unittest
|
|
import os
|
|
from PIL import Image
|
|
|
|
from pyWebLayout.concrete.page import Page
|
|
from pyWebLayout.style.fonts import Font
|
|
from pyWebLayout.abstract.block import Paragraph
|
|
from pyWebLayout.abstract.inline import Word
|
|
from pyWebLayout.typesetting.paragraph_layout import ParagraphLayout
|
|
from pyWebLayout.style.layout import Alignment
|
|
|
|
|
|
class TestParagraphLayoutFix(unittest.TestCase):
|
|
"""Test cases for paragraph layout fixes"""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures"""
|
|
self.font = Font(font_size=14)
|
|
self.words_text = [
|
|
"This", "is", "a", "very", "long", "paragraph", "that", "should",
|
|
"definitely", "wrap", "across", "multiple", "lines", "when", "rendered",
|
|
"in", "a", "narrow", "width", "container", "to", "test", "the",
|
|
"paragraph", "layout", "system", "and", "ensure", "proper", "line",
|
|
"breaking", "functionality", "works", "correctly", "as", "expected."
|
|
]
|
|
|
|
# Clean up any existing test images
|
|
test_images = [
|
|
"test_paragraph_layout_output.png",
|
|
"test_small_page.png",
|
|
"test_large_page.png"
|
|
]
|
|
for img in test_images:
|
|
if os.path.exists(img):
|
|
os.remove(img)
|
|
|
|
def tearDown(self):
|
|
"""Clean up after tests"""
|
|
# Clean up test images after each test
|
|
test_images = [
|
|
"test_paragraph_layout_output.png",
|
|
"test_small_page.png",
|
|
"test_large_page.png"
|
|
]
|
|
for img in test_images:
|
|
if os.path.exists(img):
|
|
os.remove(img)
|
|
|
|
def test_paragraph_layout_directly(self):
|
|
"""Test the paragraph layout system directly"""
|
|
# Create a paragraph with multiple words
|
|
paragraph = Paragraph()
|
|
|
|
# Add many words to force line breaking
|
|
for word_text in self.words_text:
|
|
word = Word(word_text, self.font)
|
|
paragraph.add_word(word)
|
|
|
|
# Create paragraph layout with narrow width to force wrapping
|
|
layout = ParagraphLayout(
|
|
line_width=300, # Narrow width
|
|
line_height=20,
|
|
word_spacing=(3, 8),
|
|
line_spacing=3,
|
|
halign=Alignment.LEFT
|
|
)
|
|
|
|
# Layout the paragraph
|
|
lines = layout.layout_paragraph(paragraph)
|
|
|
|
# Assertions
|
|
self.assertGreater(len(lines), 1, "Should have multiple lines")
|
|
self.assertIsInstance(lines, list)
|
|
|
|
# Check each line has content
|
|
for i, line in enumerate(lines):
|
|
if hasattr(line, 'text_objects'):
|
|
word_count = len(line.text_objects)
|
|
self.assertGreater(word_count, 0, f"Line {i+1} should have words")
|
|
|
|
def test_page_with_long_paragraph(self):
|
|
"""Test a page with manual content creation"""
|
|
# Since Page doesn't support HTML loading, test basic page functionality
|
|
# Create a page with narrower width
|
|
page = Page(size=(400, 600))
|
|
|
|
# Verify page creation
|
|
self.assertEqual(page._size[0], 400)
|
|
self.assertEqual(page._size[1], 600)
|
|
self.assertIsInstance(page._children, list)
|
|
|
|
# Try to render the empty page
|
|
image = page.render()
|
|
|
|
# Assertions
|
|
self.assertIsInstance(image, Image.Image)
|
|
self.assertEqual(image.size, (400, 600))
|
|
|
|
# Save for inspection
|
|
image.save("test_paragraph_layout_output.png")
|
|
self.assertTrue(os.path.exists("test_paragraph_layout_output.png"))
|
|
|
|
def test_simple_text_vs_paragraph(self):
|
|
"""Test different page configurations"""
|
|
# Test 1: Small page
|
|
page1 = Page(size=(400, 200))
|
|
self.assertIsInstance(page1._children, list)
|
|
|
|
# Test 2: Large page
|
|
page2 = Page(size=(800, 400))
|
|
self.assertIsInstance(page2._children, list)
|
|
|
|
# Render both
|
|
img1 = page1.render()
|
|
img2 = page2.render()
|
|
|
|
# Verify renders
|
|
self.assertIsInstance(img1, Image.Image)
|
|
self.assertIsInstance(img2, Image.Image)
|
|
self.assertEqual(img1.size, (400, 200))
|
|
self.assertEqual(img2.size, (800, 400))
|
|
|
|
# Save images
|
|
img1.save("test_small_page.png")
|
|
img2.save("test_large_page.png")
|
|
|
|
# Verify files were created
|
|
self.assertTrue(os.path.exists("test_small_page.png"))
|
|
self.assertTrue(os.path.exists("test_large_page.png"))
|
|
|
|
def test_paragraph_creation_with_words(self):
|
|
"""Test creating paragraphs with multiple words"""
|
|
paragraph = Paragraph()
|
|
|
|
# Add words to paragraph
|
|
for word_text in self.words_text[:5]: # Use first 5 words
|
|
word = Word(word_text, self.font)
|
|
paragraph.add_word(word)
|
|
|
|
# Verify paragraph has words
|
|
self.assertGreater(len(paragraph._words), 0)
|
|
|
|
def test_paragraph_layout_configuration(self):
|
|
"""Test different paragraph layout configurations"""
|
|
layouts = [
|
|
# Wide layout
|
|
ParagraphLayout(
|
|
line_width=600,
|
|
line_height=20,
|
|
word_spacing=(3, 8),
|
|
line_spacing=3,
|
|
halign=Alignment.LEFT
|
|
),
|
|
# Narrow layout
|
|
ParagraphLayout(
|
|
line_width=200,
|
|
line_height=16,
|
|
word_spacing=(2, 6),
|
|
line_spacing=2,
|
|
halign=Alignment.CENTER
|
|
),
|
|
# Justified layout
|
|
ParagraphLayout(
|
|
line_width=400,
|
|
line_height=18,
|
|
word_spacing=(4, 10),
|
|
line_spacing=4,
|
|
halign=Alignment.JUSTIFY
|
|
)
|
|
]
|
|
|
|
# Create test paragraph
|
|
paragraph = Paragraph()
|
|
for word_text in self.words_text[:10]: # Use first 10 words
|
|
word = Word(word_text, self.font)
|
|
paragraph.add_word(word)
|
|
|
|
# Test each layout
|
|
for i, layout in enumerate(layouts):
|
|
with self.subTest(layout=i):
|
|
lines = layout.layout_paragraph(paragraph)
|
|
self.assertIsInstance(lines, list)
|
|
if len(paragraph._words) > 0:
|
|
self.assertGreater(len(lines), 0, f"Layout {i} should produce lines")
|
|
|
|
def test_empty_paragraph_layout(self):
|
|
"""Test laying out an empty paragraph"""
|
|
paragraph = Paragraph()
|
|
|
|
layout = ParagraphLayout(
|
|
line_width=300,
|
|
line_height=20,
|
|
word_spacing=(3, 8),
|
|
line_spacing=3,
|
|
halign=Alignment.LEFT
|
|
)
|
|
|
|
lines = layout.layout_paragraph(paragraph)
|
|
|
|
# Empty paragraph should still return a list (might be empty)
|
|
self.assertIsInstance(lines, list)
|
|
|
|
def test_single_word_paragraph(self):
|
|
"""Test paragraph with single word"""
|
|
paragraph = Paragraph()
|
|
word = Word("Hello", self.font)
|
|
paragraph.add_word(word)
|
|
|
|
layout = ParagraphLayout(
|
|
line_width=300,
|
|
line_height=20,
|
|
word_spacing=(3, 8),
|
|
line_spacing=3,
|
|
halign=Alignment.LEFT
|
|
)
|
|
|
|
lines = layout.layout_paragraph(paragraph)
|
|
|
|
# Single word should produce at least one line
|
|
self.assertGreater(len(lines), 0)
|
|
if len(lines) > 0 and hasattr(lines[0], 'text_objects'):
|
|
self.assertGreater(len(lines[0].text_objects), 0)
|
|
|
|
def test_different_alignments(self):
|
|
"""Test paragraph layout with different alignments"""
|
|
alignments = [Alignment.LEFT, Alignment.CENTER, Alignment.RIGHT, Alignment.JUSTIFY]
|
|
|
|
# Create test paragraph
|
|
paragraph = Paragraph()
|
|
for word_text in self.words_text[:8]:
|
|
word = Word(word_text, self.font)
|
|
paragraph.add_word(word)
|
|
|
|
for alignment in alignments:
|
|
with self.subTest(alignment=alignment):
|
|
layout = ParagraphLayout(
|
|
line_width=300,
|
|
line_height=20,
|
|
word_spacing=(3, 8),
|
|
line_spacing=3,
|
|
halign=alignment
|
|
)
|
|
|
|
lines = layout.layout_paragraph(paragraph)
|
|
self.assertIsInstance(lines, list)
|
|
if len(paragraph._words) > 0:
|
|
self.assertGreater(len(lines), 0)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|