From daf1c2a37be4ef01ce9fd56cbe45bb6daf7c457a Mon Sep 17 00:00:00 2001 From: Mikan <72257910+Mikan-DS@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:26:51 +0300 Subject: [PATCH] [AI] window is not creating --- src/time_tracker/main.py | 7 +- src/time_tracker/ui/overlay.py | 19 +++-- tests/test_ui_display.py | 130 +++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+), 12 deletions(-) create mode 100644 tests/test_ui_display.py diff --git a/src/time_tracker/main.py b/src/time_tracker/main.py index 1a99a20..86cba80 100644 --- a/src/time_tracker/main.py +++ b/src/time_tracker/main.py @@ -162,6 +162,7 @@ class WorkTracker: # Check if tracking is enabled if not self.is_tracking: return False + # Check if session is locked if self.session_locked: return False @@ -276,12 +277,14 @@ class WorkTracker: def main(): # Create main Tkinter root root = tk.Tk() - root.withdraw() # Hide the root window + root.title("Work Tracker") # Give it a title so it appears in taskbar + root.geometry("1x1+2000+2000") # Minimal size off-screen to avoid flicker + # Don't call withdraw() so the window manager recognizes it # Initialize tracker tracker = WorkTracker() - # Create overlay window + # Create overlay window - this will be the visible always-on-top window overlay = OverlayWindow(root, tracker, tracker.config) # Start main tracking loop in background diff --git a/src/time_tracker/ui/overlay.py b/src/time_tracker/ui/overlay.py index aa98d6f..b325ff0 100644 --- a/src/time_tracker/ui/overlay.py +++ b/src/time_tracker/ui/overlay.py @@ -14,10 +14,9 @@ class OverlayWindow: # Configure window to be always on top self.root.attributes("-topmost", True) self.root.overrideredirect(True) # Remove window decorations - self.root.geometry("300x150+100+100") - # Make window transparent (optional) - self.root.wm_attributes("-transparentcolor", "white") + # Force the geometry to be set correctly + self.root.geometry("300x150+100+100") # Create UI elements self.create_widgets() @@ -30,28 +29,28 @@ class OverlayWindow: def create_widgets(self): """Create all UI widgets""" - # Main frame - main_frame = tk.Frame(self.root, bg='white', bd=2, relief='solid') + # Main frame with visible background + main_frame = tk.Frame(self.root, bg='#f0f0f0', bd=2, relief='solid') main_frame.pack(fill='both', expand=True, padx=2, pady=2) # Status line (tracking enabled/disabled) - self.status_label = tk.Label(main_frame, text="", bg='white', font=('Arial', 10)) + self.status_label = tk.Label(main_frame, text="", bg='#f0f0f0', font=('Arial', 10)) self.status_label.pack(anchor='w', padx=5, pady=2) # Task info - self.task_label = tk.Label(main_frame, text="", bg='white', font=('Arial', 10, 'bold')) + self.task_label = tk.Label(main_frame, text="", bg='#f0f0f0', font=('Arial', 10, 'bold')) self.task_label.pack(anchor='w', padx=5, pady=2) # Window info - self.window_label = tk.Label(main_frame, text="", bg='white', font=('Arial', 9)) + self.window_label = tk.Label(main_frame, text="", bg='#f0f0f0', font=('Arial', 9)) self.window_label.pack(anchor='w', padx=5, pady=2) # Total time info - self.total_label = tk.Label(main_frame, text="", bg='white', font=('Arial', 9)) + self.total_label = tk.Label(main_frame, text="", bg='#f0f0f0', font=('Arial', 9)) self.total_label.pack(anchor='w', padx=5, pady=2) # Buttons frame - buttons_frame = tk.Frame(main_frame, bg='white') + buttons_frame = tk.Frame(main_frame, bg='#f0f0f0') buttons_frame.pack(fill='x', padx=5, pady=5) # Tracking toggle button diff --git a/tests/test_ui_display.py b/tests/test_ui_display.py new file mode 100644 index 0000000..11dad6a --- /dev/null +++ b/tests/test_ui_display.py @@ -0,0 +1,130 @@ +import tkinter as tk +from unittest.mock import Mock +import pytest +from time_tracker.ui.overlay import OverlayWindow + + +def test_overlay_window_appears(): + """Test that overlay window actually appears and has expected widgets""" + root = tk.Tk() + root.withdraw() # Hide the root window initially + + # 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.has_active_session.return_value = False + mock_tracker.get_available_tasks.return_value = [] + + mock_config = Mock() + mock_config.tracking_enabled = True + mock_config.current_task_id = None + + # Create overlay window + overlay = OverlayWindow(root, mock_tracker, mock_config) + + # Check that the window is actually created and visible + assert overlay.root is not None + assert isinstance(overlay.root, tk.Tk) + + # Check that window properties are set + assert overlay.root.wm_attributes('-topmost') == 1 + + # Check that required widgets exist + assert hasattr(overlay, 'status_label') + assert hasattr(overlay, 'task_label') + assert hasattr(overlay, 'window_label') + assert hasattr(overlay, 'total_label') + + # Check that buttons exist + assert hasattr(overlay, 'track_btn') + + # Check that labels have been created and are not None + assert overlay.status_label is not None + assert overlay.task_label is not None + assert overlay.window_label is not None + assert overlay.total_label is not None + + # Check that the widgets are packed/grid + assert overlay.status_label.winfo_exists() == 1 + assert overlay.task_label.winfo_exists() == 1 + assert overlay.window_label.winfo_exists() == 1 + assert overlay.total_label.winfo_exists() == 1 + + root.destroy() + + +def test_overlay_window_widgets_are_visible(): + """Test that overlay window widgets are properly configured and visible""" + root = tk.Tk() + root.withdraw() + + # Mock dependencies + 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_tracker.has_active_session.return_value = True + mock_tracker.get_available_tasks.return_value = ['TASK-1', 'TASK-2'] + + mock_config = Mock() + mock_config.tracking_enabled = True + mock_config.current_task_id = 'PRJ-123' + + overlay = OverlayWindow(root, mock_tracker, mock_config) + + # Force an update to populate the labels + overlay.update_display() + + # Check that labels have text content + status_text = overlay.status_label.cget('text') + task_text = overlay.task_label.cget('text') + window_text = overlay.window_label.cget('text') + total_text = overlay.total_label.cget('text') + + # Verify that the labels contain expected information + assert 'Трекинг:' in status_text + assert 'PRJ-123' in task_text + assert 'Окно:' in window_text + assert 'Всего сегодня:' in total_text + + root.destroy() + + +def test_overlay_window_geometry(): + """Test that overlay window has correct geometry settings""" + root = tk.Tk() + root.withdraw() + + # Mock dependencies + 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.has_active_session.return_value = False + + mock_config = Mock() + mock_config.tracking_enabled = True + mock_config.current_task_id = None + + overlay = OverlayWindow(root, mock_tracker, mock_config) + + # Check that window has expected geometry + geom = overlay.root.geometry() + # The geometry should contain 300x150 for size + assert '300x150' in geom + + # Check that window is always on top + assert overlay.root.wm_attributes('-topmost') == 1 + + # Check that window is undecorated + assert overlay.root.overrideredirect() == 1 + + root.destroy() \ No newline at end of file