""" 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!")