flask_template_codex/tests/tasks/test_tasks.py
2026-08-08 03:00:29 +02:00

206 lines
5.7 KiB
Python

from datetime import datetime, timedelta
from sqlalchemy import select
from app.auth.services import create_user
from app.tasks.models import Task
from app.tasks.services import (
add_subtask,
create_task,
list_today_tasks,
toggle_subtask,
)
def create_account_and_login(client, suffix: str = "") -> None:
email = f"person{suffix}@example.com"
client.post(
"/auth/register",
data={
"username": f"steady_user{suffix}",
"email": email,
"password": "a calm secure password",
"confirm_password": "a calm secure password",
},
)
client.post(
"/auth/login",
data={"email": email, "password": "a calm secure password"},
)
def task_form_data(**overrides):
data = {
"title": "Write a gentle plan",
"description": "Start with one paragraph.",
"status": "not_started",
"priority": "normal",
"due_date": "",
}
data.update(overrides)
return data
def test_task_pages_require_login(client):
response = client.get("/tasks/")
assert response.status_code == 302
assert "/auth/login" in response.headers["Location"]
def test_create_edit_and_delete_task(client, db):
create_account_and_login(client)
create_response = client.post(
"/tasks/new",
data=task_form_data(due_date="2026-08-09T14:30"),
follow_redirects=True,
)
task = db.session.scalar(
select(Task).where(Task.title == "Write a gentle plan")
)
assert create_response.status_code == 200
assert b"Task captured" in create_response.data
assert task is not None
assert task.due_date == datetime(2026, 8, 9, 14, 30)
edit_response = client.post(
f"/tasks/{task.id}/edit",
data=task_form_data(
title="Write the first paragraph",
status="done",
priority="important",
),
follow_redirects=True,
)
db.session.refresh(task)
assert b"Task updated" in edit_response.data
assert task.title == "Write the first paragraph"
assert task.completed_at is not None
delete_response = client.post(
f"/tasks/{task.id}/delete",
follow_redirects=True,
)
assert b"Task deleted" in delete_response.data
assert db.session.get(Task, task.id) is None
def test_status_filter_only_shows_selected_tasks(client, db):
create_account_and_login(client)
client.post("/tasks/new", data=task_form_data(title="Visible active task"))
client.post(
"/tasks/new",
data=task_form_data(title="Hidden finished task", status="done"),
)
response = client.get("/tasks/?status=not_started")
assert response.status_code == 200
assert b"Visible active task" in response.data
assert b"Hidden finished task" not in response.data
def test_invalid_status_filter_is_rejected(client):
create_account_and_login(client)
response = client.get("/tasks/?status=unexpected")
assert response.status_code == 400
def test_today_is_limited_and_hides_future_and_completed_tasks(db):
user = create_user("today_user", "today@example.com", "secure password")
now = datetime(2026, 8, 8, 12, 0)
for number in range(8):
create_task(
user.id,
title=f"Inbox task {number}",
description=None,
status="not_started",
priority="normal",
due_date=None,
)
future = create_task(
user.id,
title="Future task",
description=None,
status="not_started",
priority="urgent",
due_date=now + timedelta(days=2),
)
completed = create_task(
user.id,
title="Completed task",
description=None,
status="done",
priority="urgent",
due_date=now,
)
tasks = list_today_tasks(user.id, now=now)
assert len(tasks) == 7
assert future not in tasks
assert completed not in tasks
def test_users_cannot_access_each_others_tasks(client, db):
owner = create_user("owner", "owner@example.com", "secure password")
intruder = create_user("intruder", "intruder@example.com", "secure password")
task = create_task(
owner.id,
title="Owner-only task",
description=None,
status="not_started",
priority="normal",
due_date=None,
)
client.post(
"/auth/login",
data={"email": intruder.email, "password": "secure password"},
)
assert client.get(f"/tasks/{task.id}").status_code == 404
assert client.post(f"/tasks/{task.id}/delete").status_code == 404
assert db.session.get(Task, task.id) is not None
def test_subtasks_update_derived_progress(client, db):
user = create_user("steps_user", "steps@example.com", "secure password")
task = create_task(
user.id,
title="Two-step task",
description=None,
status="in_progress",
priority="important",
due_date=None,
)
first = add_subtask(task, "First small step")
add_subtask(task, "Second small step")
assert task.progress_percentage == 0
toggle_subtask(task, first.id)
assert task.progress_percentage == 50
client.post(
"/auth/login",
data={"email": user.email, "password": "secure password"},
)
response = client.get(f"/tasks/{task.id}")
assert b"First small step" in response.data
assert b'value="50"' in response.data
def test_blank_task_title_is_rejected(client, db):
create_account_and_login(client)
response = client.post(
"/tasks/new",
data=task_form_data(title=" "),
)
assert response.status_code == 200
assert b"This field cannot be blank" in response.data
assert db.session.scalar(select(Task)) is None