100 lines
4.1 KiB
Python
100 lines
4.1 KiB
Python
"""The HTTP surface, driven the way the clients drive it."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
def test_health_and_info(client):
|
|
assert client.get("/api/health").json()["status"] == "ok"
|
|
assert "auth_required" in client.get("/api/info").json()
|
|
|
|
|
|
def test_a_whole_pomodoro_through_the_api(client):
|
|
client.put("/api/settings", json={"pomodoro": {"daily_goal_pomodoros": 1}})
|
|
task = client.post("/api/tasks", json={"title": "Write the API"}).json()
|
|
|
|
state = client.post("/api/timer/start", json={"kind": "work", "task_id": task["id"]}).json()
|
|
assert state["current"]["kind"] == "work"
|
|
assert state["current"]["task"]["title"] == "Write the API"
|
|
|
|
assert client.post("/api/timer/pause").json()["current"]["status"] == "paused"
|
|
assert client.post("/api/timer/resume").json()["current"]["status"] == "running"
|
|
assert client.post("/api/timer/extend", json={"minutes": 5}).json()["current"]["planned_seconds"] > 0
|
|
|
|
done = client.post("/api/timer/complete", json={"auto_next": False}).json()
|
|
assert done["finished"]["status"] == "completed"
|
|
assert done["completed_today"] == 1
|
|
|
|
marked = client.post(f"/api/tasks/{task['id']}/done", json={"done": True}).json()
|
|
assert marked["task"]["is_done"] is True
|
|
|
|
report = client.get("/api/reports/daily").json()
|
|
assert report["report"]["metrics"]["pomodoros"] == 1
|
|
assert "Daily report" in report["telegram_preview"]
|
|
|
|
|
|
def test_timer_errors_are_400_not_500(client):
|
|
assert client.post("/api/timer/pause").status_code == 400
|
|
assert client.post("/api/timer/complete", json={}).status_code == 400
|
|
|
|
|
|
def test_task_crud(client):
|
|
created = client.post("/api/tasks", json={"title": "Temporary", "priority": "p2"}).json()
|
|
listing = client.get("/api/tasks").json()
|
|
assert any(task["id"] == created["id"] for task in listing["tasks"])
|
|
|
|
patched = client.patch(f"/api/tasks/{created['id']}", json={"pinned": True}).json()
|
|
assert patched["pinned"] is True
|
|
|
|
client.delete(f"/api/tasks/{created['id']}")
|
|
assert all(task["id"] != created["id"] for task in client.get("/api/tasks").json()["tasks"])
|
|
|
|
|
|
def test_refresh_reports_per_source_failures_without_failing(client):
|
|
client.put(
|
|
"/api/settings",
|
|
json={"sources": {"todoist": {"enabled": True, "api_token": "definitely-invalid"}}},
|
|
)
|
|
result = client.post("/api/tasks/refresh").json()
|
|
assert result["sources"], "the enabled source should be reported"
|
|
assert result["sources"][0]["ok"] is False
|
|
assert client.get("/api/tasks").status_code == 200
|
|
|
|
|
|
def test_blocker_policy_and_events(client):
|
|
client.put(
|
|
"/api/settings",
|
|
json={"blocker": {"enabled": True, "blocked_domains": ["youtube.com"]}},
|
|
)
|
|
assert client.get("/api/blocker/policy").json()["active"] is False
|
|
|
|
client.post("/api/timer/start", json={"kind": "work"})
|
|
policy = client.get("/api/blocker/policy").json()
|
|
assert policy["active"] is True
|
|
assert "youtube.com" in policy["domains"]
|
|
|
|
client.post("/api/blocker/events", json={"kind": "domain", "target": "youtube.com"})
|
|
events = client.get("/api/blocker/events").json()
|
|
assert events["total"] == 1
|
|
|
|
|
|
def test_settings_round_trip_masks_secrets(client):
|
|
client.put("/api/settings", json={"sources": {"todoist": {"api_token": "s3cret"}}})
|
|
body = client.get("/api/settings").json()
|
|
assert body["settings"]["sources"]["todoist"]["api_token"] == "••••••••"
|
|
assert body["defaults"]["blocked_domains"]
|
|
|
|
# Posting the mask back must not wipe the token.
|
|
client.put("/api/settings", json=body["settings"])
|
|
again = client.get("/api/settings").json()
|
|
assert again["settings"]["sources"]["todoist"]["api_token"] == "••••••••"
|
|
|
|
|
|
def test_invalid_settings_are_rejected(client):
|
|
assert client.put("/api/settings", json={"pomodoro": {"work_minutes": 0}}).status_code == 422
|
|
assert client.put("/api/settings", json={"timezone": "Mars/Olympus"}).status_code == 422
|
|
|
|
|
|
def test_notification_test_endpoint_falls_back_to_the_log(client):
|
|
body = client.post("/api/notifications/test", json={}).json()
|
|
assert body["deliveries"][0]["channel"] == "log"
|