Implements 72 tests covering: - Model tests (Project, Session, Note, Change) - ProjectService tests (create, get, list, ensure structure) - SessionService tests (active session management) - FileStorage tests (read/write operations) - Complete flow tests (init -> start -> note -> stop -> show) - Note consolidation tests Uses pytest with tmp_path fixtures for isolated testing.
242 lines
7.6 KiB
Python
242 lines
7.6 KiB
Python
"""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
|