refactor: simplify dodo core experience
ci / docker (push) Successful in 3m54s

This commit is contained in:
2026-09-06 14:41:08 +08:00
parent fcaabce99f
commit d595af4f52
29 changed files with 187 additions and 955 deletions
+14 -36
View File
@@ -155,13 +155,12 @@ def test_folder_and_list_lifecycle(client):
assert client.delete(f"/api/v1/folders/{folder['id']}").status_code == 204
def test_task_search_tags_subtasks_and_recycle_bin(client):
def test_task_search_subtasks_and_recycle_bin(client):
client = initialized_client(client)
inbox = client.get("/api/v1/lists").json()[0]
tag = client.post("/api/v1/tags", json={"name": "重要", "color": "#f15a29"}).json()
parent = client.post(
"/api/v1/tasks",
json={"title": "购买咖啡豆", "description": "手冲用", "list_id": inbox["id"], "tag_ids": [tag["id"]]},
json={"title": "购买咖啡豆", "description": "手冲用", "list_id": inbox["id"]},
).json()
child = client.post(
"/api/v1/tasks",
@@ -170,11 +169,11 @@ def test_task_search_tags_subtasks_and_recycle_bin(client):
assert child.status_code == 201
detail = client.get(f"/api/v1/tasks/{parent['id']}")
assert detail.status_code == 200
assert detail.json()["tags"][0]["name"] == "重要"
assert "tags" not in detail.json()
assert len(detail.json()["subtasks"]) == 1
listed = client.get("/api/v1/tasks", params={"q": "咖啡"}).json()["items"]
assert len(listed) == 1
assert listed[0]["tags"][0]["name"] == "重要"
assert "tags" not in listed[0]
assert listed[0]["subtasks"][0]["title"] == "比较价格"
assert client.delete(f"/api/v1/tasks/{parent['id']}").status_code == 204
@@ -264,33 +263,13 @@ def test_nested_subtasks_are_rejected(client):
assert nested.status_code == 400
def test_tags_are_global_searchable_and_validated(client):
def test_restore_replace_recovers_habits_and_task_links_without_tags(client):
client = initialized_client(client)
inbox = client.get("/api/v1/lists").json()[0]
errands = client.post("/api/v1/lists", json={"name": "跑腿清单"}).json()
tag = client.post("/api/v1/tags", json={"name": "蓝色标签", "color": "#123abc"})
assert tag.status_code == 201
assert client.get("/api/v1/tags").json()[0]["color"] == "#123abc"
task = client.post(
"/api/v1/tasks",
json={"title": "普通标题", "description": "特殊说明", "list_id": errands["id"], "tag_ids": [tag.json()["id"]]},
).json()
for query in ("普通", "特殊", "蓝色", "跑腿"):
assert [row["id"] for row in client.get("/api/v1/tasks", params={"q": query}).json()["items"]] == [task["id"]]
invalid = client.post(
"/api/v1/tasks",
json={"title": "非法标签", "list_id": inbox["id"], "tag_ids": ["00000000-0000-0000-0000-000000000001"]},
)
assert invalid.status_code == 404
def test_restore_replace_recovers_tags_habits_and_task_links(client):
client = initialized_client(client)
inbox = client.get("/api/v1/lists").json()[0]
tag = client.post("/api/v1/tags", json={"name": "备份标签", "color": "#f15a29"}).json()
client.post(
"/api/v1/tasks",
json={"title": "备份任务", "list_id": inbox["id"], "tag_ids": [tag["id"]]},
json={"title": "备份任务", "list_id": inbox["id"]},
).json()
client.post(
"/api/v1/habits",
@@ -298,8 +277,9 @@ def test_restore_replace_recovers_tags_habits_and_task_links(client):
).json()
exported = client.get("/api/v1/export")
assert exported.status_code == 200
assert "tags" not in exported.json()
assert "task_tags" not in exported.json()
client.post("/api/v1/tags", json={"name": "现有标签", "color": "#123abc"})
client.post(
"/api/v1/habits",
json={"name": "深蹲", "kind": "boolean", "schedule_type": "daily"},
@@ -307,12 +287,11 @@ def test_restore_replace_recovers_tags_habits_and_task_links(client):
restored = client.post("/api/v1/restore?mode=replace", json=exported.json())
assert restored.status_code == 200
tags = client.get("/api/v1/tags").json()
assert [row["name"] for row in tags] == ["备份标签"]
assert client.get("/api/v1/tags").status_code == 404
habits = client.get("/api/v1/habits").json()
assert [row["name"] for row in habits] == ["俯卧撑"]
listed = client.get("/api/v1/tasks", params={"q": "备份任务"}).json()["items"]
assert listed[0]["tags"][0]["name"] == "备份标签"
assert "tags" not in listed[0]
def test_recycle_bin_restore_and_permanent_delete_include_subtasks(client):
@@ -333,10 +312,9 @@ def test_recycle_bin_restore_and_permanent_delete_include_subtasks(client):
assert client.post(f"/api/v1/tasks/{parent['id']}/restore").status_code == 404
def test_batch_supports_due_date_tags_and_soft_delete_atomically(client):
def test_batch_supports_due_date_and_soft_delete_atomically(client):
client = initialized_client(client)
inbox = client.get("/api/v1/lists").json()[0]
tag = client.post("/api/v1/tags", json={"name": "批量", "color": "red"}).json()
ids = [
client.post("/api/v1/tasks", json={"title": str(i), "list_id": inbox["id"]}).json()["id"]
for i in range(2)
@@ -344,10 +322,10 @@ def test_batch_supports_due_date_tags_and_soft_delete_atomically(client):
due_at = "2026-09-10T08:00:00+08:00"
response = client.post(
"/api/v1/tasks/batch",
json={"task_ids": ids, "due_at": due_at, "tag_ids": [tag["id"]]},
json={"task_ids": ids, "due_at": due_at},
)
assert response.status_code == 200 and response.json()["updated"] == 2
assert all(client.get(f"/api/v1/tasks/{task_id}").json()["tags"] for task_id in ids)
assert all(client.get(f"/api/v1/tasks/{task_id}").json()["due_at"] is not None for task_id in ids)
parent = client.post("/api/v1/tasks", json={"title": "", "list_id": inbox["id"]}).json()
client.post(