""" Tests for theme manager menu functionality. """ import os import sys import unittest from unittest.mock import Mock, patch import tkinter as tk # Add src to path for imports sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src')) from theme_manager import ThemeManager class TestThemeManagerMenu(unittest.TestCase): """Test cases for theme manager menu functionality.""" def setUp(self): """Set up test fixtures.""" self.root = tk.Tk() self.root.withdraw() # Hide the window during testing self.mock_logger = Mock() self.theme_manager = ThemeManager(self.root, self.mock_logger) def tearDown(self): """Clean up after tests.""" if self.root: self.root.destroy() def test_get_menu_colors(self): """Test that get_menu_colors returns valid color dictionary.""" colors = self.theme_manager.get_menu_colors() # Check that all required keys are present required_keys = ["bg", "fg", "active_bg", "active_fg", "disabled_fg"] for key in required_keys: self.assertIn(key, colors) # Check that colors are valid hex strings or named colors for key, color in colors.items(): self.assertIsInstance(color, str) self.assertTrue(len(color) > 0) def test_configure_menu(self): """Test that configure_menu applies theme to menu widget.""" menu = tk.Menu(self.root) # Configure the menu self.theme_manager.configure_menu(menu) # Check that menu configuration was called # Note: We can't directly test the visual appearance, but we can # verify that no exceptions were raised self.assertIsNotNone(menu) def test_create_themed_menu(self): """Test that create_themed_menu creates and themes a menu.""" menu = self.theme_manager.create_themed_menu(self.root, tearoff=0) # Check that a menu was created self.assertIsInstance(menu, tk.Menu) # Check that the menu has the tearoff option set self.assertEqual(menu['tearoff'], 0) def test_menu_colors_consistency(self): """Test that menu colors are consistent across theme changes.""" original_colors = self.theme_manager.get_menu_colors() # Try to apply a different theme available_themes = self.theme_manager.get_available_themes() if len(available_themes) > 1: # Apply a different theme other_theme = available_themes[1] if available_themes[0] == self.theme_manager.current_theme else available_themes[0] self.theme_manager.apply_theme(other_theme) # Get new colors new_colors = self.theme_manager.get_menu_colors() # Colors should still have the same structure self.assertEqual(set(original_colors.keys()), set(new_colors.keys())) # Colors might be different (which is expected) # Just ensure they're still valid for color in new_colors.values(): self.assertIsInstance(color, str) self.assertTrue(len(color) > 0) @patch('tkinter.Menu') def test_create_themed_menu_error_handling(self, mock_menu_class): """Test that create_themed_menu handles errors gracefully.""" # Make the Menu constructor raise an exception mock_menu_class.side_effect = Exception("Test error") # This should not raise an exception but return a fallback menu menu = self.theme_manager.create_themed_menu(self.root) # The method should still return something (fallback behavior) self.assertIsNotNone(menu) def test_menu_theme_integration(self): """Test complete menu theming workflow.""" # Create a menu structure similar to the main application menubar = self.theme_manager.create_themed_menu(self.root) file_menu = self.theme_manager.create_themed_menu(menubar, tearoff=0) theme_menu = self.theme_manager.create_themed_menu(menubar, tearoff=0) # Add some menu items file_menu.add_command(label="Test Item 1") file_menu.add_separator() file_menu.add_command(label="Test Item 2") # Add theme selection items available_themes = self.theme_manager.get_available_themes() for theme in available_themes: theme_menu.add_radiobutton(label=theme.title()) # Verify structure was created successfully self.assertIsInstance(menubar, tk.Menu) self.assertIsInstance(file_menu, tk.Menu) self.assertIsInstance(theme_menu, tk.Menu) if __name__ == '__main__': unittest.main()