flask_template_codex/tests/tasks/test_focus.py
2026-08-08 03:08:28 +02:00

173 lines
5.7 KiB
Python

from datetime import date, datetime
from app.auth.services import create_user
from app.tasks.services import (
calculate_forgiving_streak,
complete_task,
create_task,
)
def login(client, email: str, password: str = "secure password") -> None:
client.post(
"/auth/login",
data={"email": email, "password": password},
)
def make_task(user_id: int, title: str, *, priority: str = "normal"):
return create_task(
user_id,
title=title,
description=None,
status="not_started",
priority=priority,
due_date=None,
)
def test_focus_mode_surfaces_only_highest_ranked_today_task(client, db):
user = create_user("focus_user", "focus@example.com", "secure password")
make_task(user.id, "Lower priority choice")
primary = make_task(user.id, "Primary urgent choice", priority="urgent")
login(client, user.email)
response = client.get("/tasks/focus")
assert response.status_code == 200
assert b"Primary urgent choice" in response.data
assert b"Lower priority choice" not in response.data
assert f'data-task-id="{primary.id}"'.encode() not in response.data
def test_focus_settings_store_timer_context_and_chunks(client, db):
user = create_user("setup_user", "setup@example.com", "secure password")
task = make_task(user.id, "Configured focus task")
login(client, user.email)
response = client.post(
f"/tasks/{task.id}/focus-settings",
data={
"timer_minutes": "25",
"context": "At my desk with headphones",
"chunk_plan": "5, 5, 10",
},
follow_redirects=True,
)
db.session.refresh(task)
assert response.status_code == 200
assert b"Focus setup saved" in response.data
assert b"Visual countdown" in response.data
assert b"At my desk with headphones" in response.data
assert task.timer_seconds == 1500
assert task.context == "At my desk with headphones"
assert task.chunk_sessions == [
{"minutes": 5, "completed": False},
{"minutes": 5, "completed": False},
{"minutes": 10, "completed": False},
]
def test_invalid_chunk_plan_is_rejected_without_changes(client, db):
user = create_user("invalid_user", "invalid@example.com", "secure password")
task = make_task(user.id, "Unchanged focus task")
login(client, user.email)
response = client.post(
f"/tasks/{task.id}/focus-settings",
data={"timer_minutes": "10", "chunk_plan": "5, later, 10"},
follow_redirects=True,
)
db.session.refresh(task)
assert b"Use comma-separated whole minutes" in response.data
assert task.timer_seconds == 0
assert task.chunk_sessions == []
def test_chunk_toggle_updates_only_requested_block(client, db):
user = create_user("chunk_user", "chunk@example.com", "secure password")
task = make_task(user.id, "Chunked task")
task.chunk_sessions = [
{"minutes": 5, "completed": False},
{"minutes": 10, "completed": False},
]
db.session.commit()
login(client, user.email)
response = client.post(
f"/tasks/{task.id}/chunks/1/toggle",
follow_redirects=True,
)
db.session.refresh(task)
assert response.status_code == 200
assert task.chunk_sessions[0]["completed"] is False
assert task.chunk_sessions[1]["completed"] is True
assert client.post(f"/tasks/{task.id}/chunks/4/toggle").status_code == 404
def test_completion_celebrates_and_advances_to_next_task(client, db):
user = create_user("complete_user", "complete@example.com", "secure password")
primary = make_task(user.id, "Finish this first", priority="urgent")
make_task(user.id, "Then show this task")
login(client, user.email)
response = client.post(
f"/tasks/{primary.id}/complete",
follow_redirects=True,
)
db.session.refresh(primary)
assert response.status_code == 200
assert b"That step is complete" in response.data
assert b'id="focus-task-title">Then show this task' in response.data
assert b'id="focus-task-title">Finish this first' not in response.data
assert primary.status == "done"
assert primary.completed_at is not None
def test_focus_mutations_do_not_expose_foreign_tasks(client, db):
owner = create_user("focus_owner", "focus-owner@example.com", "secure password")
visitor = create_user(
"focus_visitor",
"focus-visitor@example.com",
"secure password",
)
task = make_task(owner.id, "Private focus task")
login(client, visitor.email)
assert client.get(f"/tasks/{task.id}/focus").status_code == 404
assert client.post(f"/tasks/{task.id}/complete").status_code == 404
assert (
client.post(
f"/tasks/{task.id}/focus-settings",
data={"timer_minutes": "15"},
).status_code
== 404
)
assert client.post(f"/tasks/{task.id}/chunks/0/toggle").status_code == 404
def test_forgiving_streak_allows_one_internal_rest_day(db):
user = create_user("streak_user", "streak@example.com", "secure password")
for day in (8, 7, 5):
task = make_task(user.id, f"Completed on day {day}")
complete_task(task, completed_at=datetime(2026, 8, day, 12, 0))
streak = calculate_forgiving_streak(user.id, today=date(2026, 8, 8))
assert streak.days == 3
assert streak.freeze_used is True
def test_current_incomplete_day_does_not_break_streak(db):
user = create_user("rest_user", "rest@example.com", "secure password")
yesterday = make_task(user.id, "Yesterday counted")
complete_task(yesterday, completed_at=datetime(2026, 8, 7, 12, 0))
streak = calculate_forgiving_streak(user.id, today=date(2026, 8, 8))
assert streak.days == 1
assert streak.freeze_used is False