import tkinter as tk from unittest.mock import Mock, patch, MagicMock import pytest from time_tracker.ui.overlay import OverlayWindow def test_overlay_window_creation(): """Test that overlay window is created correctly""" root = tk.Tk() root.withdraw() # Hide the root window # Mock dependencies with proper return values mock_tracker = Mock() mock_tracker.get_current_session_duration.return_value = 0 mock_tracker.get_total_work_today.return_value = 0 mock_tracker.get_planned_duration.return_value = None mock_tracker.active_window = 'Desktop' mock_tracker.window_classification = 'neutral' mock_config = Mock() mock_config.tracking_enabled = True mock_config.current_task_id = None # Create overlay - this should not raise an exception overlay = OverlayWindow(root, mock_tracker, mock_config) # Check that window properties are set assert overlay.root.wm_attributes('-topmost') == 1 assert overlay.root.overrideredirect() is True # Check that labels exist assert hasattr(overlay, 'status_label') assert hasattr(overlay, 'task_label') assert hasattr(overlay, 'window_label') root.destroy() def test_update_display_with_active_task(): """Test updating display with an active task""" root = tk.Tk() root.withdraw() # Mock dependencies with proper return values mock_tracker = Mock() mock_tracker.get_current_session_duration.return_value = 3600 # 1 hour mock_tracker.get_total_work_today.return_value = 7200 # 2 hours mock_tracker.get_planned_duration.return_value = None mock_tracker.active_window = 'PyCharm' mock_tracker.window_classification = 'work' mock_config = Mock() mock_config.tracking_enabled = True mock_config.current_task_id = 'PRJ-123' overlay = OverlayWindow(root, mock_tracker, mock_config) overlay.update_display() # Check that labels were updated (we can check the text property) assert 'PRJ-123' in overlay.task_label.cget('text') # The task label should contain the duration, not the status label assert '1ч00м' in overlay.task_label.cget('text') root.destroy() def test_update_display_without_active_task(): """Test updating display when no active task""" root = tk.Tk() root.withdraw() # Mock dependencies with proper return values mock_tracker = Mock() mock_tracker.get_current_session_duration.return_value = 0 mock_tracker.get_total_work_today.return_value = 0 mock_tracker.get_planned_duration.return_value = None mock_tracker.active_window = 'Desktop' mock_tracker.window_classification = 'neutral' mock_config = Mock() mock_config.tracking_enabled = True mock_config.current_task_id = None overlay = OverlayWindow(root, mock_tracker, mock_config) overlay.update_display() # Check that labels show appropriate messages assert 'Нет активной задачи' in overlay.task_label.cget('text') root.destroy() def test_toggle_tracking_callback(): """Test that toggle tracking button works""" root = tk.Tk() root.withdraw() # Mock dependencies with proper return values mock_tracker = Mock() mock_tracker.get_current_session_duration.return_value = 0 mock_tracker.get_total_work_today.return_value = 0 mock_tracker.get_planned_duration.return_value = None mock_tracker.active_window = 'Desktop' mock_tracker.window_classification = 'neutral' mock_config = Mock() mock_config.tracking_enabled = True mock_config.current_task_id = None overlay = OverlayWindow(root, mock_tracker, mock_config) # Call the toggle method overlay.toggle_tracking() # Verify that the tracker's toggle method was called mock_tracker.toggle_tracking.assert_called_once() root.destroy() def test_new_task_callback(): """Test that new task button opens dialog""" root = tk.Tk() root.withdraw() # Mock dependencies with proper return values mock_tracker = Mock() mock_tracker.get_current_session_duration.return_value = 0 mock_tracker.get_total_work_today.return_value = 0 mock_tracker.get_planned_duration.return_value = None mock_tracker.active_window = 'Desktop' mock_tracker.window_classification = 'neutral' mock_config = Mock() mock_config.tracking_enabled = True mock_config.current_task_id = None overlay = OverlayWindow(root, mock_tracker, mock_config) # Mock the simpledialog with patch('tkinter.simpledialog.askstring') as mock_dialog: mock_dialog.return_value = 'NEW-456' overlay.new_task() # Verify that the tracker's create_task method was called mock_tracker.create_task.assert_called_once_with('NEW-456') root.destroy() def test_switch_task_callback(): """Test that switch task button works""" root = tk.Tk() root.withdraw() # Mock dependencies with proper return values mock_tracker = Mock() mock_tracker.get_current_session_duration.return_value = 0 mock_tracker.get_total_work_today.return_value = 0 mock_tracker.get_planned_duration.return_value = None mock_tracker.active_window = 'Desktop' mock_tracker.window_classification = 'neutral' mock_tracker.get_available_tasks.return_value = ['TASK-1', 'TASK-2', 'TASK-3'] mock_config = Mock() mock_config.tracking_enabled = True mock_config.current_task_id = None overlay = OverlayWindow(root, mock_tracker, mock_config) # Mock the selection dialog with patch('tkinter.simpledialog.askstring') as mock_dialog: mock_dialog.return_value = 'TASK-2' overlay.switch_task() # Verify that the tracker's switch_task method was called mock_tracker.switch_task.assert_called_once_with('TASK-2') root.destroy() def test_adjust_time_callback(): """Test that adjust time button opens dialog""" root = tk.Tk() root.withdraw() # Mock dependencies with proper return values mock_tracker = Mock() mock_tracker.get_current_session_duration.return_value = 0 mock_tracker.get_total_work_today.return_value = 0 mock_tracker.get_planned_duration.return_value = None mock_tracker.active_window = 'Desktop' mock_tracker.window_classification = 'neutral' mock_config = Mock() mock_config.tracking_enabled = True mock_config.current_task_id = None overlay = OverlayWindow(root, mock_tracker, mock_config) # Mock the adjustment dialog with patch.object(overlay, 'show_adjust_time_dialog') as mock_dialog: overlay.adjust_time() mock_dialog.assert_called_once() root.destroy()