""" Unit tests for HTML style management. Tests the HTMLStyleManager class for CSS parsing, style stacks, and font creation. """ import unittest from pyWebLayout.io.readers.html_style import HTMLStyleManager from pyWebLayout.style import FontStyle, FontWeight, TextDecoration class TestHTMLStyleManager(unittest.TestCase): """Test cases for HTMLStyleManager.""" def setUp(self): """Set up test fixtures.""" self.style_manager = HTMLStyleManager() def test_initialization(self): """Test proper initialization of style manager.""" style = self.style_manager.get_current_style() self.assertEqual(style['font_size'], 12) self.assertEqual(style['font_weight'], FontWeight.NORMAL) self.assertEqual(style['font_style'], FontStyle.NORMAL) self.assertEqual(style['decoration'], TextDecoration.NONE) self.assertEqual(style['color'], (0, 0, 0)) self.assertIsNone(style['background']) self.assertEqual(style['language'], 'en_US') def test_style_stack_operations(self): """Test push and pop operations on style stack.""" # Initial state initial_style = self.style_manager.get_current_style() # Push a new style new_style = {'font_size': 16, 'font_weight': FontWeight.BOLD} self.style_manager.push_style(new_style) current_style = self.style_manager.get_current_style() self.assertEqual(current_style['font_size'], 16) self.assertEqual(current_style['font_weight'], FontWeight.BOLD) self.assertEqual(current_style['color'], (0, 0, 0)) # Unchanged # Pop the style self.style_manager.pop_style() restored_style = self.style_manager.get_current_style() self.assertEqual(restored_style, initial_style) def test_tag_styles(self): """Test default styles for HTML tags.""" h1_style = self.style_manager.get_tag_style('h1') self.assertEqual(h1_style['font_size'], 24) self.assertEqual(h1_style['font_weight'], FontWeight.BOLD) h6_style = self.style_manager.get_tag_style('h6') self.assertEqual(h6_style['font_size'], 12) self.assertEqual(h6_style['font_weight'], FontWeight.BOLD) em_style = self.style_manager.get_tag_style('em') self.assertEqual(em_style['font_style'], FontStyle.ITALIC) unknown_style = self.style_manager.get_tag_style('unknown') self.assertEqual(unknown_style, {}) def test_inline_style_parsing(self): """Test parsing of inline CSS styles.""" # Test font-size style = self.style_manager.parse_inline_style('font-size: 18px') self.assertEqual(style['font_size'], 18) style = self.style_manager.parse_inline_style('font-size: 14pt') self.assertEqual(style['font_size'], 14) # Test font-weight style = self.style_manager.parse_inline_style('font-weight: bold') self.assertEqual(style['font_weight'], FontWeight.BOLD) # Test font-style style = self.style_manager.parse_inline_style('font-style: italic') self.assertEqual(style['font_style'], FontStyle.ITALIC) # Test text-decoration style = self.style_manager.parse_inline_style('text-decoration: underline') self.assertEqual(style['decoration'], TextDecoration.UNDERLINE) # Test multiple properties style = self.style_manager.parse_inline_style( 'font-size: 20px; font-weight: bold; color: red' ) self.assertEqual(style['font_size'], 20) self.assertEqual(style['font_weight'], FontWeight.BOLD) self.assertEqual(style['color'], (255, 0, 0)) def test_color_parsing(self): """Test CSS color parsing.""" # Named colors self.assertEqual(self.style_manager.parse_color('red'), (255, 0, 0)) self.assertEqual(self.style_manager.parse_color('blue'), (0, 0, 255)) self.assertEqual(self.style_manager.parse_color('white'), (255, 255, 255)) self.assertEqual(self.style_manager.parse_color('gray'), (128, 128, 128)) self.assertEqual(self.style_manager.parse_color('grey'), (128, 128, 128)) # Hex colors self.assertEqual(self.style_manager.parse_color('#ff0000'), (255, 0, 0)) self.assertEqual(self.style_manager.parse_color('#00ff00'), (0, 255, 0)) self.assertEqual(self.style_manager.parse_color('#f00'), (255, 0, 0)) self.assertEqual(self.style_manager.parse_color('#0f0'), (0, 255, 0)) # RGB colors self.assertEqual(self.style_manager.parse_color('rgb(255, 0, 0)'), (255, 0, 0)) self.assertEqual(self.style_manager.parse_color('rgb(128, 128, 128)'), (128, 128, 128)) self.assertEqual(self.style_manager.parse_color('rgb( 255 , 255 , 255 )'), (255, 255, 255)) # RGBA colors (alpha ignored) self.assertEqual(self.style_manager.parse_color('rgba(255, 0, 0, 0.5)'), (255, 0, 0)) # Invalid colors self.assertIsNone(self.style_manager.parse_color('invalid')) self.assertIsNone(self.style_manager.parse_color('#gg0000')) self.assertIsNone(self.style_manager.parse_color('rgb(300, 0, 0)')) # Invalid values return None def test_color_clamping(self): """Test that RGB values outside valid range return None.""" # Values outside 0-255 range should return None color = self.style_manager.parse_color('rgb(300, -10, 128)') self.assertIsNone(color) # Invalid values return None def test_apply_style_to_element(self): """Test combining tag styles with inline styles.""" # Test h1 with inline style attrs = {'style': 'color: blue; font-size: 30px'} combined = self.style_manager.apply_style_to_element('h1', attrs) # Should have h1 defaults plus inline overrides self.assertEqual(combined['font_size'], 30) # Overridden self.assertEqual(combined['font_weight'], FontWeight.BOLD) # From h1 self.assertEqual(combined['color'], (0, 0, 255)) # Inline # Test without inline styles combined = self.style_manager.apply_style_to_element('strong', {}) self.assertEqual(combined['font_weight'], FontWeight.BOLD) def test_reset(self): """Test resetting the style manager.""" # Change the state self.style_manager.push_style({'font_size': 20}) self.style_manager.push_style({'color': (255, 0, 0)}) # Reset self.style_manager.reset() # Should be back to initial state style = self.style_manager.get_current_style() self.assertEqual(style['font_size'], 12) self.assertEqual(style['color'], (0, 0, 0)) self.assertEqual(len(self.style_manager._style_stack), 0) def test_font_creation(self): """Test Font object creation from current style.""" # Set some specific styles self.style_manager.push_style({ 'font_size': 16, 'font_weight': FontWeight.BOLD, 'font_style': FontStyle.ITALIC, 'decoration': TextDecoration.UNDERLINE, 'color': (255, 0, 0), 'background': (255, 255, 0, 255) }) font = self.style_manager.create_font() self.assertEqual(font.font_size, 16) self.assertEqual(font.weight, FontWeight.BOLD) self.assertEqual(font.style, FontStyle.ITALIC) self.assertEqual(font.decoration, TextDecoration.UNDERLINE) self.assertEqual(font.colour, (255, 0, 0)) self.assertEqual(font.background, (255, 255, 0, 255)) if __name__ == '__main__': unittest.main()