"""Tests for gui/utils.py module.""" class TestValidatePort: """Tests for validate_port function.""" def test_valid_port_minimum(self): """Port 1 is valid.""" from gui.utils import validate_port assert validate_port("1") is True def test_valid_port_maximum(self): """Port 65535 is valid.""" from gui.utils import validate_port assert validate_port("65535") is True def test_valid_port_common(self): """Common ports are valid.""" from gui.utils import validate_port assert validate_port("80") is True assert validate_port("443") is True assert validate_port("2048") is True assert validate_port("8080") is True def test_invalid_port_zero(self): """Port 0 is invalid.""" from gui.utils import validate_port assert validate_port("0") is False def test_invalid_port_negative(self): """Negative port is invalid.""" from gui.utils import validate_port assert validate_port("-1") is False def test_invalid_port_too_large(self): """Port > 65535 is invalid.""" from gui.utils import validate_port assert validate_port("65536") is False assert validate_port("99999") is False def test_invalid_port_non_numeric(self): """Non-numeric string is invalid.""" from gui.utils import validate_port assert validate_port("abc") is False assert validate_port("") is False assert validate_port("12.34") is False def test_port_with_spaces_stripped(self): """Python int() strips whitespace, so these are valid.""" from gui.utils import validate_port assert validate_port(" 80") is True assert validate_port("80 ") is True assert validate_port(" 80 ") is True class TestFormatUptime: """Tests for format_uptime function.""" def test_zero_seconds(self): """0 seconds formats as 00:00.""" from gui.utils import format_uptime assert format_uptime(0) == "00:00" def test_seconds_only(self): """Seconds < 60 format as 00:SS.""" from gui.utils import format_uptime assert format_uptime(30) == "00:30" assert format_uptime(59) == "00:59" def test_minutes_and_seconds(self): """Minutes format as MM:SS.""" from gui.utils import format_uptime assert format_uptime(60) == "01:00" assert format_uptime(90) == "01:30" assert format_uptime(600) == "10:00" assert format_uptime(3599) == "59:59" def test_hours_minutes_seconds(self): """Hours format as HH:MM:SS.""" from gui.utils import format_uptime assert format_uptime(3600) == "01:00:00" assert format_uptime(3661) == "01:01:01" assert format_uptime(7200) == "02:00:00" assert format_uptime(86399) == "23:59:59" def test_large_uptime(self): """Large uptime formats correctly.""" from gui.utils import format_uptime assert format_uptime(86400) == "24:00:00" assert format_uptime(360000) == "100:00:00" class TestCopyToClipboard: """Tests for copy_to_clipboard function.""" def test_copy_clears_clipboard(self, mock_tk_root): """copy_to_clipboard calls clipboard_clear.""" from gui.utils import copy_to_clipboard copy_to_clipboard(mock_tk_root, "test") mock_tk_root.clipboard_clear.assert_called_once() def test_copy_appends_text(self, mock_tk_root): """copy_to_clipboard appends the text.""" from gui.utils import copy_to_clipboard copy_to_clipboard(mock_tk_root, "hello world") mock_tk_root.clipboard_append.assert_called_once_with("hello world") def test_copy_calls_update(self, mock_tk_root): """copy_to_clipboard calls update to persist.""" from gui.utils import copy_to_clipboard copy_to_clipboard(mock_tk_root, "test") mock_tk_root.update.assert_called_once() class TestCTkTooltip: """Tests for CTkTooltip class.""" def test_tooltip_class_exists(self): """CTkTooltip class should be importable.""" from gui.utils import CTkTooltip assert CTkTooltip is not None def test_tooltip_alias_exists(self): """Tooltip alias should exist for backwards compatibility.""" from gui.utils import CTkTooltip, Tooltip assert Tooltip is CTkTooltip def test_tooltip_binds_events(self, mock_widget): """CTkTooltip binds hover events.""" from gui.utils import CTkTooltip CTkTooltip(mock_widget, "tooltip_account") # Should bind at least 3 events assert mock_widget.bind.call_count >= 3 # Check event types call_args = [call[0][0] for call in mock_widget.bind.call_args_list] assert "" in call_args assert "" in call_args assert "" in call_args def test_tooltip_stores_text_key(self, mock_widget): """CTkTooltip stores the text key for translation.""" from gui.utils import CTkTooltip tooltip = CTkTooltip(mock_widget, "tooltip_fastapi_port") assert tooltip.text_key == "tooltip_fastapi_port" def test_tooltip_initially_hidden(self, mock_widget): """CTkTooltip window is None initially.""" from gui.utils import CTkTooltip tooltip = CTkTooltip(mock_widget, "tooltip_test") assert tooltip.tooltip_window is None class TestCTkScrollableList: """Tests for CTkScrollableList class.""" def test_scrollable_list_class_exists(self): """CTkScrollableList class is importable.""" from gui.utils import CTkScrollableList assert CTkScrollableList is not None def test_scrollable_list_alias_exists(self): """ScrollableListbox alias should exist for backwards compatibility.""" from gui.utils import CTkScrollableList, ScrollableListbox assert ScrollableListbox is CTkScrollableList def test_scrollable_list_has_required_methods(self): """CTkScrollableList has required methods.""" from gui.utils import CTkScrollableList assert hasattr(CTkScrollableList, "add_item") assert hasattr(CTkScrollableList, "clear") assert hasattr(CTkScrollableList, "get_selected") assert hasattr(CTkScrollableList, "get_items") assert hasattr(CTkScrollableList, "select") assert hasattr(CTkScrollableList, "bind_select") assert hasattr(CTkScrollableList, "bind_double_click") def test_scrollable_list_uses_colors(self): """CTkScrollableList uses COLORS from config.""" from gui.config import COLORS # Verify colors needed for the list exist assert "bg_light" in COLORS assert "text_primary" in COLORS assert "accent" in COLORS assert "border" in COLORS class TestCTkStatusBar: """Tests for CTkStatusBar class.""" def test_status_bar_class_exists(self): """CTkStatusBar class is importable.""" from gui.utils import CTkStatusBar assert CTkStatusBar is not None def test_status_bar_alias_exists(self): """StatusBar alias should exist for backwards compatibility.""" from gui.utils import CTkStatusBar, StatusBar assert StatusBar is CTkStatusBar def test_status_bar_has_required_methods(self): """CTkStatusBar has required methods.""" from gui.utils import CTkStatusBar assert hasattr(CTkStatusBar, "set_status") assert hasattr(CTkStatusBar, "set_port") assert hasattr(CTkStatusBar, "start_uptime") assert hasattr(CTkStatusBar, "stop_uptime") def test_status_bar_default_status_text(self): """StatusBar should display 'Ready' by default.""" from gui.i18n import get_text, set_language set_language("en") ready_text = get_text("statusbar_ready") assert "Ready" in ready_text or ready_text == "Ready" def test_format_uptime_used_in_status_bar(self): """StatusBar uses format_uptime for display.""" from gui.utils import format_uptime assert format_uptime(3661) == "01:01:01"