feat: Implement Minimum Viable Calm (MVC) feature and initial tests
This commit is contained in:
229
tests/dashboard/test_calm.py
Normal file
229
tests/dashboard/test_calm.py
Normal file
@@ -0,0 +1,229 @@
|
||||
import pytest
|
||||
import sys
|
||||
from datetime import date
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker, Session
|
||||
|
||||
sys.path.insert(0, "/home/ubuntu/Timmy-time-dashboard/src")
|
||||
from src.dashboard.app import app
|
||||
from src.dashboard.models.database import Base, get_db
|
||||
from src.dashboard.models.calm import Task, JournalEntry, TaskState, TaskCertainty
|
||||
|
||||
|
||||
@pytest.fixture(name="test_db_engine")
|
||||
def test_db_engine_fixture():
|
||||
# Create a new in-memory SQLite database for each test
|
||||
engine = create_engine("sqlite:///:memory:", connect_args={"check_same_thread": False})
|
||||
Base.metadata.create_all(bind=engine) # Create tables
|
||||
yield engine
|
||||
Base.metadata.drop_all(bind=engine) # Drop tables after test
|
||||
|
||||
|
||||
@pytest.fixture(name="db_session")
|
||||
def db_session_fixture(test_db_engine):
|
||||
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=test_db_engine)
|
||||
db = TestingSessionLocal()
|
||||
try:
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def client_fixture(db_session: Session):
|
||||
app.dependency_overrides[get_db] = lambda: db_session
|
||||
with TestClient(app) as client:
|
||||
yield client
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
def test_create_task(client: TestClient, db_session: Session):
|
||||
response = client.post(
|
||||
"/calm/tasks",
|
||||
data={
|
||||
"title": "Test Task",
|
||||
"description": "This is a test description",
|
||||
"is_mit": False,
|
||||
"certainty": TaskCertainty.SOFT.value,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert "later_count-container" in response.text
|
||||
|
||||
task = db_session.query(Task).filter(Task.title == "Test Task").first()
|
||||
assert task is not None
|
||||
assert task.state == TaskState.LATER
|
||||
assert task.description == "This is a test description"
|
||||
|
||||
|
||||
def test_morning_ritual_creates_tasks_and_journal_entry(client: TestClient, db_session: Session):
|
||||
response = client.post(
|
||||
"/calm/ritual/morning",
|
||||
data={
|
||||
"mit1_title": "MIT Task 1",
|
||||
"mit2_title": "MIT Task 2",
|
||||
"other_tasks": "Other Task 1\nOther Task 2",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert "Timmy Calm" in response.text
|
||||
|
||||
journal_entry = db_session.query(JournalEntry).first()
|
||||
assert journal_entry is not None
|
||||
assert len(journal_entry.mit_task_ids) == 2
|
||||
|
||||
tasks = db_session.query(Task).all()
|
||||
assert len(tasks) == 4
|
||||
|
||||
mit_tasks = db_session.query(Task).filter(Task.is_mit == True).all()
|
||||
assert len(mit_tasks) == 2
|
||||
|
||||
now_task = db_session.query(Task).filter(Task.state == TaskState.NOW).first()
|
||||
next_task = db_session.query(Task).filter(Task.state == TaskState.NEXT).first()
|
||||
later_tasks = db_session.query(Task).filter(Task.state == TaskState.LATER).all()
|
||||
|
||||
assert now_task is not None
|
||||
assert next_task is not None
|
||||
assert len(later_tasks) == 2
|
||||
|
||||
|
||||
def test_complete_now_task_promotes_next_and_later(client: TestClient, db_session: Session):
|
||||
task_now = Task(title="Task NOW", state=TaskState.NOW, is_mit=True, sort_order=0)
|
||||
task_next = Task(title="Task NEXT", state=TaskState.NEXT, is_mit=False, sort_order=0)
|
||||
task_later1 = Task(title="Task LATER 1", state=TaskState.LATER, is_mit=True, sort_order=0)
|
||||
task_later2 = Task(title="Task LATER 2", state=TaskState.LATER, is_mit=False, sort_order=1)
|
||||
db_session.add_all([task_now, task_next, task_later1, task_later2])
|
||||
db_session.commit()
|
||||
db_session.refresh(task_now)
|
||||
db_session.refresh(task_next)
|
||||
db_session.refresh(task_later1)
|
||||
db_session.refresh(task_later2)
|
||||
|
||||
response = client.post(f"/calm/tasks/{task_now.id}/complete")
|
||||
assert response.status_code == 200
|
||||
|
||||
assert db_session.query(Task).filter(Task.id == task_now.id).first().state == TaskState.DONE
|
||||
assert db_session.query(Task).filter(Task.id == task_next.id).first().state == TaskState.NOW
|
||||
assert db_session.query(Task).filter(Task.id == task_later1.id).first().state == TaskState.NEXT
|
||||
assert db_session.query(Task).filter(Task.id == task_later2.id).first().state == TaskState.LATER
|
||||
|
||||
|
||||
def test_defer_now_task_promotes_next_and_later(client: TestClient, db_session: Session):
|
||||
task_now = Task(title="Task NOW", state=TaskState.NOW, is_mit=True, sort_order=0)
|
||||
task_next = Task(title="Task NEXT", state=TaskState.NEXT, is_mit=False, sort_order=0)
|
||||
task_later1 = Task(title="Task LATER 1", state=TaskState.LATER, is_mit=True, sort_order=0)
|
||||
task_later2 = Task(title="Task LATER 2", state=TaskState.LATER, is_mit=False, sort_order=1)
|
||||
db_session.add_all([task_now, task_next, task_later1, task_later2])
|
||||
db_session.commit()
|
||||
db_session.refresh(task_now)
|
||||
db_session.refresh(task_next)
|
||||
db_session.refresh(task_later1)
|
||||
db_session.refresh(task_later2)
|
||||
|
||||
response = client.post(f"/calm/tasks/{task_now.id}/defer")
|
||||
assert response.status_code == 200
|
||||
|
||||
assert db_session.query(Task).filter(Task.id == task_now.id).first().state == TaskState.DEFERRED
|
||||
assert db_session.query(Task).filter(Task.id == task_next.id).first().state == TaskState.NOW
|
||||
assert db_session.query(Task).filter(Task.id == task_later1.id).first().state == TaskState.NEXT
|
||||
assert db_session.query(Task).filter(Task.id == task_later2.id).first().state == TaskState.LATER
|
||||
|
||||
|
||||
def test_start_task_demotes_current_now_and_promotes_to_now(client: TestClient, db_session: Session):
|
||||
task_now = Task(title="Task NOW", state=TaskState.NOW, is_mit=True, sort_order=0)
|
||||
task_next = Task(title="Task NEXT", state=TaskState.NEXT, is_mit=False, sort_order=0)
|
||||
task_later1 = Task(title="Task LATER 1", state=TaskState.LATER, is_mit=True, sort_order=0)
|
||||
db_session.add_all([task_now, task_next, task_later1])
|
||||
db_session.commit()
|
||||
db_session.refresh(task_now)
|
||||
db_session.refresh(task_next)
|
||||
db_session.refresh(task_later1)
|
||||
|
||||
response = client.post(f"/calm/tasks/{task_later1.id}/start")
|
||||
assert response.status_code == 200
|
||||
|
||||
assert db_session.query(Task).filter(Task.id == task_later1.id).first().state == TaskState.NOW
|
||||
assert db_session.query(Task).filter(Task.id == task_now.id).first().state == TaskState.NEXT
|
||||
assert db_session.query(Task).filter(Task.id == task_next.id).first().state == TaskState.LATER
|
||||
|
||||
|
||||
def test_evening_ritual_archives_active_tasks(client: TestClient, db_session: Session):
|
||||
journal_entry = JournalEntry(entry_date=date.today())
|
||||
db_session.add(journal_entry)
|
||||
db_session.commit()
|
||||
db_session.refresh(journal_entry)
|
||||
|
||||
task_now = Task(title="Task NOW", state=TaskState.NOW)
|
||||
task_next = Task(title="Task NEXT", state=TaskState.NEXT)
|
||||
task_later = Task(title="Task LATER", state=TaskState.LATER)
|
||||
task_done = Task(title="Task DONE", state=TaskState.DONE)
|
||||
db_session.add_all([task_now, task_next, task_later, task_done])
|
||||
db_session.commit()
|
||||
|
||||
response = client.post(
|
||||
"/calm/ritual/evening",
|
||||
data={
|
||||
"evening_reflection": "Reflected well",
|
||||
"gratitude": "Grateful for everything",
|
||||
"energy_level": 8,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert "Evening Ritual Complete" in response.text
|
||||
|
||||
assert db_session.query(Task).filter(Task.id == task_now.id).first().state == TaskState.DEFERRED
|
||||
assert db_session.query(Task).filter(Task.id == task_next.id).first().state == TaskState.DEFERRED
|
||||
assert db_session.query(Task).filter(Task.id == task_later.id).first().state == TaskState.DEFERRED
|
||||
assert db_session.query(Task).filter(Task.id == task_done.id).first().state == TaskState.DONE
|
||||
|
||||
updated_journal = db_session.query(JournalEntry).filter(JournalEntry.id == journal_entry.id).first()
|
||||
assert updated_journal.evening_reflection == "Reflected well"
|
||||
assert updated_journal.gratitude == "Grateful for everything"
|
||||
assert updated_journal.energy_level == 8
|
||||
|
||||
|
||||
def test_reorder_later_tasks(client: TestClient, db_session: Session):
|
||||
task_later1 = Task(title="Task LATER 1", state=TaskState.LATER, sort_order=0)
|
||||
task_later2 = Task(title="Task LATER 2", state=TaskState.LATER, sort_order=1)
|
||||
task_later3 = Task(title="Task LATER 3", state=TaskState.LATER, sort_order=2)
|
||||
db_session.add_all([task_later1, task_later2, task_later3])
|
||||
db_session.commit()
|
||||
db_session.refresh(task_later1)
|
||||
db_session.refresh(task_later2)
|
||||
db_session.refresh(task_later3)
|
||||
|
||||
response = client.post(
|
||||
"/calm/tasks/reorder",
|
||||
data={
|
||||
"later_task_ids": f"{task_later3.id},{task_later1.id},{task_later2.id}"
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
assert db_session.query(Task).filter(Task.id == task_later3.id).first().sort_order == 0
|
||||
assert db_session.query(Task).filter(Task.id == task_later1.id).first().sort_order == 1
|
||||
assert db_session.query(Task).filter(Task.id == task_later2.id).first().sort_order == 2
|
||||
|
||||
|
||||
def test_reorder_promote_later_to_next(client: TestClient, db_session: Session):
|
||||
task_now = Task(title="Task NOW", state=TaskState.NOW, is_mit=True, sort_order=0)
|
||||
task_later1 = Task(title="Task LATER 1", state=TaskState.LATER, is_mit=False, sort_order=0)
|
||||
task_later2 = Task(title="Task LATER 2", state=TaskState.LATER, is_mit=False, sort_order=1)
|
||||
db_session.add_all([task_now, task_later1, task_later2])
|
||||
db_session.commit()
|
||||
db_session.refresh(task_now)
|
||||
db_session.refresh(task_later1)
|
||||
db_session.refresh(task_later2)
|
||||
|
||||
response = client.post(
|
||||
"/calm/tasks/reorder",
|
||||
data={
|
||||
"next_task_id": task_later1.id
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
assert db_session.query(Task).filter(Task.id == task_now.id).first().state == TaskState.NOW
|
||||
assert db_session.query(Task).filter(Task.id == task_later1.id).first().state == TaskState.NEXT
|
||||
assert db_session.query(Task).filter(Task.id == task_later2.id).first().state == TaskState.LATER
|
||||
Reference in New Issue
Block a user