FastAPI + SQLAlchemy/Alembic + MariaDB backend with Jinja2/htmx/Alpine server-rendered frontend. Multi-user via Google OAuth, daily habit tracking, monthly/weekly history views, Web Push reminders via APScheduler, and PWA support (manifest, service worker, offline caching). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
82 lines
3.0 KiB
Python
82 lines
3.0 KiB
Python
from app.models.habit import ALL_WEEKDAYS_MASK, HabitType
|
|
from app.schemas.habit import HabitCreate
|
|
from app.services import habit_service
|
|
|
|
|
|
def _make_habit(db_session, user_id, name="테스트 습관"):
|
|
data = HabitCreate(name=name, habit_type=HabitType.BUILD, weekdays_mask=ALL_WEEKDAYS_MASK)
|
|
return habit_service.create_habit(db_session, user_id, data)
|
|
|
|
|
|
def test_list_habits_requires_login(client):
|
|
response = client.get("/api/habits")
|
|
assert response.status_code == 401
|
|
|
|
|
|
def test_create_and_list_habit(auth_client):
|
|
response = auth_client.post(
|
|
"/api/habits", json={"name": "아침 운동", "habit_type": "build", "weekdays_mask": ALL_WEEKDAYS_MASK}
|
|
)
|
|
assert response.status_code == 201
|
|
created = response.json()
|
|
assert created["name"] == "아침 운동"
|
|
|
|
listed = auth_client.get("/api/habits").json()
|
|
assert [h["name"] for h in listed] == ["아침 운동"]
|
|
|
|
|
|
def test_create_habit_rejects_blank_name(auth_client):
|
|
response = auth_client.post(
|
|
"/api/habits", json={"name": " ", "habit_type": "build", "weekdays_mask": ALL_WEEKDAYS_MASK}
|
|
)
|
|
assert response.status_code == 422
|
|
|
|
|
|
def test_get_other_users_habit_returns_404(auth_client, db_session, other_user):
|
|
others_habit = _make_habit(db_session, other_user.id, name="남의 습관")
|
|
|
|
response = auth_client.get(f"/api/habits/{others_habit.id}")
|
|
assert response.status_code == 404
|
|
|
|
|
|
def test_delete_other_users_habit_returns_404_and_does_not_delete(auth_client, db_session, other_user):
|
|
others_habit = _make_habit(db_session, other_user.id, name="남의 습관")
|
|
|
|
response = auth_client.delete(f"/api/habits/{others_habit.id}")
|
|
assert response.status_code == 404
|
|
assert habit_service.get_habit(db_session, others_habit.id, other_user.id) is not None
|
|
|
|
|
|
def test_update_own_habit(auth_client, db_session, test_user):
|
|
habit = _make_habit(db_session, test_user.id, name="원래 이름")
|
|
|
|
response = auth_client.put(
|
|
f"/api/habits/{habit.id}",
|
|
json={"name": "새 이름", "habit_type": "build", "weekdays_mask": ALL_WEEKDAYS_MASK},
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.json()["name"] == "새 이름"
|
|
|
|
|
|
def test_complete_and_reactivate_habit(auth_client, db_session, test_user):
|
|
habit = _make_habit(db_session, test_user.id)
|
|
|
|
complete_res = auth_client.post(f"/api/habits/{habit.id}/complete")
|
|
assert complete_res.status_code == 200
|
|
assert complete_res.json()["status"] == "completed"
|
|
|
|
reactivate_res = auth_client.post(f"/api/habits/{habit.id}/reactivate")
|
|
assert reactivate_res.status_code == 200
|
|
assert reactivate_res.json()["status"] == "active"
|
|
|
|
|
|
def test_reorder_endpoint(auth_client, db_session, test_user):
|
|
a = _make_habit(db_session, test_user.id, name="A")
|
|
b = _make_habit(db_session, test_user.id, name="B")
|
|
|
|
response = auth_client.post("/api/habits/reorder", json={"habit_ids": [b.id, a.id]})
|
|
assert response.status_code == 200
|
|
|
|
listed = auth_client.get("/api/habits").json()
|
|
assert [h["name"] for h in listed] == ["B", "A"]
|