151 lines
5.6 KiB
Python
151 lines
5.6 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.
|
|
"""
|
|
|
|
import pytest
|
|
from pyWebLayout.style.abstract_style import AbstractStyle, AbstractStyleRegistry
|
|
from pyWebLayout.style.concrete_style import ConcreteStyle, 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!")
|