pyWebLayout/tests/style/test_word_spacing_constraints.py

150 lines
5.4 KiB
Python

"""
Test file demonstrating word spacing constraints functionality.
This test shows how to use the new min/max word spacing constraints
in the style system.
"""
from pyWebLayout.style.abstract_style import AbstractStyle, AbstractStyleRegistry
from pyWebLayout.style.concrete_style import StyleResolver, RenderingContext
class TestWordSpacingConstraints:
"""Test cases for word spacing constraints feature."""
def test_abstract_style_with_word_spacing_constraints(self):
"""Test that AbstractStyle accepts word spacing constraint fields."""
style = AbstractStyle(
word_spacing=5.0,
word_spacing_min=2.0,
word_spacing_max=10.0
)
assert style.word_spacing == 5.0
assert style.word_spacing_min == 2.0
assert style.word_spacing_max == 10.0
def test_concrete_style_resolution_with_constraints(self):
"""Test that word spacing constraints are resolved correctly."""
# Create rendering context
context = RenderingContext(base_font_size=16)
resolver = StyleResolver(context)
# Create abstract style with constraints
abstract_style = AbstractStyle(
word_spacing=5.0,
word_spacing_min=2.0,
word_spacing_max=12.0
)
# Resolve to concrete style
concrete_style = resolver.resolve_style(abstract_style)
# Check that constraints are preserved
assert concrete_style.word_spacing == 5.0
assert concrete_style.word_spacing_min == 2.0
assert concrete_style.word_spacing_max == 12.0
def test_default_constraint_logic(self):
"""Test default constraint logic when not specified."""
context = RenderingContext(base_font_size=16)
resolver = StyleResolver(context)
# Style with only base word spacing
abstract_style = AbstractStyle(word_spacing=6.0)
concrete_style = resolver.resolve_style(abstract_style)
# Should apply default logic: min = base, max = base * 2
assert concrete_style.word_spacing == 6.0
assert concrete_style.word_spacing_min == 6.0
assert concrete_style.word_spacing_max == 12.0
def test_no_word_spacing_defaults(self):
"""Test defaults when no word spacing is specified."""
context = RenderingContext(base_font_size=16)
resolver = StyleResolver(context)
# Style with no word spacing specified
abstract_style = AbstractStyle()
concrete_style = resolver.resolve_style(abstract_style)
# Should apply font-based defaults
assert concrete_style.word_spacing == 0.0
assert concrete_style.word_spacing_min == 2.0 # Minimum default
assert concrete_style.word_spacing_max == 8.0 # 50% of font size (16 * 0.5)
def test_partial_constraints(self):
"""Test behavior when only min or max is specified."""
context = RenderingContext(base_font_size=16)
resolver = StyleResolver(context)
# Only min specified
abstract_style_min = AbstractStyle(
word_spacing=4.0,
word_spacing_min=3.0
)
concrete_style_min = resolver.resolve_style(abstract_style_min)
assert concrete_style_min.word_spacing_min == 3.0
assert concrete_style_min.word_spacing_max == 6.0 # 3.0 * 2
# Only max specified
abstract_style_max = AbstractStyle(
word_spacing=4.0,
word_spacing_max=8.0
)
concrete_style_max = resolver.resolve_style(abstract_style_max)
assert concrete_style_max.word_spacing_min == 4.0 # max(word_spacing, 2.0)
assert concrete_style_max.word_spacing_max == 8.0
def test_style_registry_with_constraints(self):
"""Test that style registry handles word spacing constraints."""
registry = AbstractStyleRegistry()
# Create style with constraints
style_id, style = registry.get_or_create_style(
word_spacing=5.0,
word_spacing_min=3.0,
word_spacing_max=10.0
)
# Verify the style was created correctly
retrieved_style = registry.get_style_by_id(style_id)
assert retrieved_style.word_spacing == 5.0
assert retrieved_style.word_spacing_min == 3.0
assert retrieved_style.word_spacing_max == 10.0
def test_em_units_in_constraints(self):
"""Test that em units work in word spacing constraints."""
context = RenderingContext(base_font_size=16)
resolver = StyleResolver(context)
# Use em units
abstract_style = AbstractStyle(
word_spacing="0.25em",
word_spacing_min="0.1em",
word_spacing_max="0.5em"
)
concrete_style = resolver.resolve_style(abstract_style)
# Should convert em to pixels based on font size (16px)
assert concrete_style.word_spacing == 4.0 # 0.25 * 16
assert concrete_style.word_spacing_min == 1.6 # 0.1 * 16
assert concrete_style.word_spacing_max == 8.0 # 0.5 * 16
if __name__ == "__main__":
# Run basic tests
test = TestWordSpacingConstraints()
test.test_abstract_style_with_word_spacing_constraints()
test.test_concrete_style_resolution_with_constraints()
test.test_default_constraint_logic()
test.test_no_word_spacing_defaults()
test.test_partial_constraints()
test.test_style_registry_with_constraints()
test.test_em_units_in_constraints()
print("All word spacing constraint tests passed!")