"""Tests for SessionService.""" import json from datetime import datetime from pathlib import Path from unittest.mock import patch, MagicMock import pytest from tracker.models import Session from tracker.services import ( get_active_session, set_active_session, clear_active_session, get_active_session_path, validate_no_other_active_session, ) @pytest.fixture def mock_active_session_path(tmp_path, monkeypatch): """Mock the active session path to use tmp_path.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) return fake_path class TestSetAndGetActiveSession: """Tests for set and get active session functions.""" def test_set_and_get_active_session(self, tmp_path, mock_session, monkeypatch): """Test setting and getting an active session.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) set_active_session(mock_session) retrieved = get_active_session() assert retrieved is not None assert retrieved.id == mock_session.id assert retrieved.project_slug == mock_session.project_slug assert retrieved.started_at == mock_session.started_at def test_get_active_session_returns_none_when_no_session(self, tmp_path, monkeypatch): """Test that get_active_session returns None when no session exists.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) result = get_active_session() assert result is None def test_set_active_session_creates_parent_directories(self, tmp_path, mock_session, monkeypatch): """Test that set_active_session creates parent directories if needed.""" fake_path = tmp_path / "subdir" / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) set_active_session(mock_session) assert fake_path.exists() def test_active_session_contains_all_fields(self, tmp_path, mock_session, monkeypatch): """Test that active session file contains all session fields.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) set_active_session(mock_session) with open(fake_path, "r") as f: data = json.load(f) assert data["id"] == mock_session.id assert data["project_slug"] == mock_session.project_slug assert "started_at" in data assert "work_done" in data assert data["work_done"] == mock_session.work_done class TestClearActiveSession: """Tests for clear_active_session function.""" def test_clear_active_session_removes_file(self, tmp_path, mock_session, monkeypatch): """Test that clear_active_session removes the active session file.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) set_active_session(mock_session) assert fake_path.exists() clear_active_session() assert not fake_path.exists() def test_clear_active_session_when_no_session(self, tmp_path, monkeypatch): """Test that clear_active_session does not error when no session exists.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) clear_active_session() assert not fake_path.exists() def test_get_active_session_after_clear(self, tmp_path, mock_session, monkeypatch): """Test that get_active_session returns None after clearing.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) set_active_session(mock_session) clear_active_session() result = get_active_session() assert result is None class TestValidateNoOtherActiveSession: """Tests for validate_no_other_active_session function.""" def test_validate_no_other_active_session_returns_true_when_none(self, tmp_path, monkeypatch): """Test validation returns True when no active session exists.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) result = validate_no_other_active_session("any-project") assert result is True def test_validate_no_other_active_session_returns_true_for_same_project( self, tmp_path, mock_session, monkeypatch ): """Test validation returns True for same project's session.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) set_active_session(mock_session) result = validate_no_other_active_session(mock_session.project_slug) assert result is True def test_validate_no_other_active_session_returns_false_for_different_project( self, tmp_path, mock_session, monkeypatch ): """Test validation returns False for different project's session.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) set_active_session(mock_session) result = validate_no_other_active_session("different-project") assert result is False def test_validate_no_other_active_session_with_no_active_after_clear( self, tmp_path, mock_session, monkeypatch ): """Test validation returns True after clearing session.""" fake_path = tmp_path / ".active_session.json" def mock_get_active_session_path(): return fake_path monkeypatch.setattr( "tracker.services.session_service.get_active_session_path", mock_get_active_session_path ) set_active_session(mock_session) clear_active_session() result = validate_no_other_active_session("any-project") assert result is True