"""Тесты M3: дерево подзадач (родитель, циклы) и карточка проекта."""
from fastapi.testclient import TestClient
def test_create_subtask(client: TestClient) -> None:
parent = client.post("/api/tasks", json={"title": "Ремонт балкона"}).json()["id"]
child = client.post(
"/api/tasks", json={"title": "Купить краску", "parent_task_id": parent}
).json()["id"]
task = client.get(f"/api/tasks/{child}").json()
assert task["parent_task_id"] == parent
root = client.get(f"/api/tasks/{parent}").json()
assert root["parent_task_id"] is None
def test_subtask_of_unknown_parent_rejected(client: TestClient) -> None:
resp = client.post("/api/tasks", json={"title": "x", "parent_task_id": 999})
assert resp.status_code == 400
def test_task_cannot_be_own_parent(client: TestClient) -> None:
task_id = client.post("/api/tasks", json={"title": "x"}).json()["id"]
resp = client.patch(f"/api/tasks/{task_id}", json={"parent_task_id": task_id})
assert resp.status_code == 400
def test_cycle_rejected_on_reparent(client: TestClient) -> None:
a = client.post("/api/tasks", json={"title": "A"}).json()["id"]
b = client.post("/api/tasks", json={"title": "B", "parent_task_id": a}).json()["id"]
c = client.post("/api/tasks", json={"title": "C", "parent_task_id": b}).json()["id"]
# c → a создало бы цикл a → b → c → a
assert client.patch(f"/api/tasks/{a}", json={"parent_task_id": c}).status_code == 400
# валидный перенос: c → a
moved = client.patch(f"/api/tasks/{c}", json={"parent_task_id": a}).json()
assert moved["parent_task_id"] == a
def test_detach_from_parent(client: TestClient) -> None:
parent = client.post("/api/tasks", json={"title": "P"}).json()["id"]
child_id = client.post(
"/api/tasks", json={"title": "C", "parent_task_id": parent}
).json()["id"]
detached = client.patch(f"/api/tasks/{child_id}", json={"parent_task_id": None}).json()
assert detached["parent_task_id"] is None
def test_get_single_project(client: TestClient) -> None:
pid = client.post(
"/api/projects", json={"name": "Дача", "note": "Ссылки: [форум](https://example.com)"}
).json()["id"]
project = client.get(f"/api/projects/{pid}").json()
assert project["name"] == "Дача"
assert "форум" in project["note"]
assert client.get("/api/projects/999").status_code == 404
def test_project_note_update(client: TestClient) -> None:
pid = client.post("/api/projects", json={"name": "Проект"}).json()["id"]
updated = client.patch(
f"/api/projects/{pid}",
json={"note": "- задача 1\n- задача 2", "relevance_status": "paused"},
).json()
assert updated["note"].startswith("- задача 1")
assert updated["relevance_status"] == "paused"