increase test coverage.

This commit is contained in:
2025-06-07 17:33:11 +02:00
parent fa8ba244a8
commit 5b2c24e59d
3 changed files with 368 additions and 123 deletions
+337 -1
View File
@@ -7,7 +7,7 @@ and formatting within documents.
import unittest
from unittest.mock import Mock, patch, MagicMock
from pyWebLayout.abstract.inline import Word, FormattedSpan
from pyWebLayout.abstract.inline import Word, FormattedSpan, LineBreak
from pyWebLayout.style import Font
@@ -251,6 +251,150 @@ class TestWord(unittest.TestCase):
# Test getting individual parts
for i, expected_part in enumerate(expected_parts):
self.assertEqual(word.get_hyphenated_part(i), expected_part)
def test_word_create_and_add_to_with_container_style(self):
"""Test Word.create_and_add_to with container that has style property."""
# Create mock container with style and add_word method
mock_container = Mock()
mock_container.style = self.font
mock_container.add_word = Mock()
# Ensure _words and background don't interfere
del mock_container._words
del mock_container.background # Remove background so it inherits from font
# Create and add word
word = Word.create_and_add_to("hello", mock_container)
# Test that word was created with correct properties
self.assertIsInstance(word, Word)
self.assertEqual(word.text, "hello")
self.assertEqual(word.style, self.font)
self.assertEqual(word.background, self.font.background)
# Test that add_word was called
mock_container.add_word.assert_called_once_with(word)
def test_word_create_and_add_to_with_style_override(self):
"""Test Word.create_and_add_to with explicit style parameter."""
# Create alternate font
alt_font = Font()
# Create mock container
mock_container = Mock()
mock_container.style = self.font
mock_container.add_word = Mock()
# Ensure _words doesn't interfere
del mock_container._words
# Create word with style override
word = Word.create_and_add_to("test", mock_container, style=alt_font)
# Test that word uses the override style, not container style
self.assertEqual(word.style, alt_font)
self.assertNotEqual(word.style, self.font)
def test_word_create_and_add_to_with_background_override(self):
"""Test Word.create_and_add_to with explicit background parameter."""
# Create mock container
mock_container = Mock()
mock_container.style = self.font
mock_container.background = "container_bg"
mock_container.add_word = Mock()
# Ensure _words doesn't interfere
del mock_container._words
# Create word with background override
word = Word.create_and_add_to("test", mock_container, background="override_bg")
# Test that word uses the override background
self.assertEqual(word.background, "override_bg")
def test_word_create_and_add_to_inherit_container_background(self):
"""Test Word.create_and_add_to inheriting background from container."""
# Create mock container with background
mock_container = Mock()
mock_container.style = self.font
mock_container.background = "container_bg"
mock_container.add_word = Mock()
# Ensure _words doesn't interfere
del mock_container._words
# Create word without background override
word = Word.create_and_add_to("test", mock_container)
# Test that word inherits container background
self.assertEqual(word.background, "container_bg")
def test_word_create_and_add_to_with_words_list_previous(self):
"""Test Word.create_and_add_to linking with previous word from _words list."""
# Create mock container with _words list
mock_container = Mock()
mock_container.style = self.font
mock_container.add_word = Mock()
# Create existing word and add to container's _words list
existing_word = Word("previous", self.font)
mock_container._words = [existing_word]
# Create new word
word = Word.create_and_add_to("current", mock_container)
# Test that words are linked
self.assertEqual(word.previous, existing_word)
self.assertEqual(existing_word.next, word)
def test_word_create_and_add_to_with_words_method_previous(self):
"""Test Word.create_and_add_to linking with previous word from words() method."""
# Create a simple container that implements words() method
class SimpleContainer:
def __init__(self, font):
self.style = font
self.existing_word = Word("previous", font)
def words(self):
yield ("span1", self.existing_word)
def add_word(self, word):
pass # Simple implementation
container = SimpleContainer(self.font)
# Create new word
word = Word.create_and_add_to("current", container)
# Test that words are linked
self.assertEqual(word.previous, container.existing_word)
self.assertEqual(container.existing_word.next, word)
def test_word_create_and_add_to_no_style_error(self):
"""Test Word.create_and_add_to raises error when container has no style."""
# Create container without style
class BadContainer:
def add_word(self, word):
pass
container = BadContainer()
# Test that AttributeError is raised
with self.assertRaises(AttributeError) as context:
Word.create_and_add_to("test", container)
self.assertIn("must have a 'style' property", str(context.exception))
def test_word_create_and_add_to_no_add_word_error(self):
"""Test Word.create_and_add_to raises error when container has no add_word method."""
# Create container without add_word
class BadContainer:
def __init__(self, font):
self.style = font
container = BadContainer(self.font)
# Test that AttributeError is raised
with self.assertRaises(AttributeError) as context:
Word.create_and_add_to("test", container)
self.assertIn("must have an 'add_word' method", str(context.exception))
class TestFormattedSpan(unittest.TestCase):
@@ -386,6 +530,97 @@ class TestFormattedSpan(unittest.TestCase):
first_word = span.add_word("first")
self.assertIsNone(first_word.previous)
self.assertIsNone(first_word.next)
def test_formatted_span_create_and_add_to_with_container_style(self):
"""Test FormattedSpan.create_and_add_to with container that has style property."""
# Create mock container with style and add_span method
mock_container = Mock()
mock_container.style = self.font
mock_container.add_span = Mock()
# Remove background so it inherits from font
del mock_container.background
# Create and add span
span = FormattedSpan.create_and_add_to(mock_container)
# Test that span was created with correct properties
self.assertIsInstance(span, FormattedSpan)
self.assertEqual(span.style, self.font)
self.assertEqual(span.background, self.font.background)
# Test that add_span was called
mock_container.add_span.assert_called_once_with(span)
def test_formatted_span_create_and_add_to_with_style_override(self):
"""Test FormattedSpan.create_and_add_to with explicit style parameter."""
# Create alternate font
alt_font = Font()
# Create mock container
mock_container = Mock()
mock_container.style = self.font
mock_container.add_span = Mock()
# Create span with style override
span = FormattedSpan.create_and_add_to(mock_container, style=alt_font)
# Test that span uses the override style, not container style
self.assertEqual(span.style, alt_font)
self.assertNotEqual(span.style, self.font)
def test_formatted_span_create_and_add_to_with_background_override(self):
"""Test FormattedSpan.create_and_add_to with explicit background parameter."""
# Create mock container
mock_container = Mock()
mock_container.style = self.font
mock_container.background = "container_bg"
mock_container.add_span = Mock()
# Create span with background override
span = FormattedSpan.create_and_add_to(mock_container, background="override_bg")
# Test that span uses the override background
self.assertEqual(span.background, "override_bg")
def test_formatted_span_create_and_add_to_inherit_container_background(self):
"""Test FormattedSpan.create_and_add_to inheriting background from container."""
# Create mock container with background
mock_container = Mock()
mock_container.style = self.font
mock_container.background = "container_bg"
mock_container.add_span = Mock()
# Create span without background override
span = FormattedSpan.create_and_add_to(mock_container)
# Test that span inherits container background
self.assertEqual(span.background, "container_bg")
def test_formatted_span_create_and_add_to_no_style_error(self):
"""Test FormattedSpan.create_and_add_to raises error when container has no style."""
# Create mock container without style
mock_container = Mock()
del mock_container.style
mock_container.add_span = Mock()
# Test that AttributeError is raised
with self.assertRaises(AttributeError) as context:
FormattedSpan.create_and_add_to(mock_container)
self.assertIn("must have a 'style' property", str(context.exception))
def test_formatted_span_create_and_add_to_no_add_span_error(self):
"""Test FormattedSpan.create_and_add_to raises error when container has no add_span method."""
# Create mock container without add_span
mock_container = Mock()
mock_container.style = self.font
del mock_container.add_span
# Test that AttributeError is raised
with self.assertRaises(AttributeError) as context:
FormattedSpan.create_and_add_to(mock_container)
self.assertIn("must have an 'add_span' method", str(context.exception))
class TestWordFormattedSpanIntegration(unittest.TestCase):
@@ -516,5 +751,106 @@ class TestWordFormattedSpanIntegration(unittest.TestCase):
self.assertEqual(span.words[0].text, "original")
class TestLineBreak(unittest.TestCase):
"""Test cases for LineBreak class."""
def test_line_break_creation(self):
"""Test line break creation."""
line_break = LineBreak()
# Test initial state
self.assertIsNotNone(line_break.block_type)
self.assertIsNone(line_break.parent)
def test_line_break_block_type(self):
"""Test line break block type property."""
line_break = LineBreak()
# Import BlockType to verify the correct type
from pyWebLayout.abstract.block import BlockType
self.assertEqual(line_break.block_type, BlockType.LINE_BREAK)
def test_line_break_parent_property(self):
"""Test line break parent property getter and setter."""
line_break = LineBreak()
# Test initial state
self.assertIsNone(line_break.parent)
# Test setter
mock_parent = Mock()
line_break.parent = mock_parent
self.assertEqual(line_break.parent, mock_parent)
# Test setting to None
line_break.parent = None
self.assertIsNone(line_break.parent)
def test_line_break_create_and_add_to_with_add_line_break(self):
"""Test LineBreak.create_and_add_to with container that has add_line_break method."""
# Create mock container with add_line_break method
mock_container = Mock()
mock_container.add_line_break = Mock()
# Create and add line break
line_break = LineBreak.create_and_add_to(mock_container)
# Test that line break was created
self.assertIsInstance(line_break, LineBreak)
# Test that add_line_break was called
mock_container.add_line_break.assert_called_once_with(line_break)
def test_line_break_create_and_add_to_with_add_element(self):
"""Test LineBreak.create_and_add_to with container that has add_element method."""
# Create mock container without add_line_break but with add_element
mock_container = Mock()
del mock_container.add_line_break # Ensure no add_line_break method
mock_container.add_element = Mock()
# Create and add line break
line_break = LineBreak.create_and_add_to(mock_container)
# Test that line break was created
self.assertIsInstance(line_break, LineBreak)
# Test that add_element was called
mock_container.add_element.assert_called_once_with(line_break)
def test_line_break_create_and_add_to_with_add_word(self):
"""Test LineBreak.create_and_add_to with container that has add_word method."""
# Create mock container with only add_word method
mock_container = Mock()
del mock_container.add_line_break # Ensure no add_line_break method
del mock_container.add_element # Ensure no add_element method
mock_container.add_word = Mock()
# Create and add line break
line_break = LineBreak.create_and_add_to(mock_container)
# Test that line break was created
self.assertIsInstance(line_break, LineBreak)
# Test that add_word was called
mock_container.add_word.assert_called_once_with(line_break)
def test_line_break_create_and_add_to_fallback(self):
"""Test LineBreak.create_and_add_to fallback behavior when no add methods available."""
# Create mock container without any add methods
mock_container = Mock()
del mock_container.add_line_break
del mock_container.add_element
del mock_container.add_word
# Create and add line break
line_break = LineBreak.create_and_add_to(mock_container)
# Test that line break was created
self.assertIsInstance(line_break, LineBreak)
# Test that parent was set manually
self.assertEqual(line_break.parent, mock_container)
if __name__ == '__main__':
unittest.main()