refactor: remove manual refresh and search controls
ci / gitleaks (push) Successful in 8s
ci / docker (push) Successful in 7m17s

This commit is contained in:
2026-09-19 21:15:23 +08:00
parent 0cf1c49094
commit 4973d56a64
29 changed files with 244 additions and 860 deletions
+4 -2
View File
@@ -244,7 +244,8 @@ def test_after_completion_recurrence_survives_json_and_csv_round_trips(client):
restored = client.post("/api/v1/restore?mode=merge", json=exported)
assert restored.status_code == 200
restored_task = client.get("/api/v1/tasks", params={"q": task["title"]}).json()["items"][0]
restored_items = client.get("/api/v1/tasks", params={"limit": 100}).json()["items"]
restored_task = next(item for item in restored_items if item["title"] == task["title"])
restored_recurrence = client.get(f"/api/v1/tasks/{restored_task['id']}/recurrence").json()
assert restored_recurrence["trigger_mode"] == "after_completion"
assert restored_recurrence["after_completion_days"] == 2
@@ -256,7 +257,8 @@ def test_after_completion_recurrence_survives_json_and_csv_round_trips(client):
files={"file": ("dodo-export.csv", csv_export.content, "text/csv")},
)
assert csv_restore.status_code == 200
csv_task = client.get("/api/v1/tasks", params={"q": task["title"]}).json()["items"][0]
csv_items = client.get("/api/v1/tasks", params={"limit": 100}).json()["items"]
csv_task = next(item for item in csv_items if item["title"] == task["title"])
assert client.get(f"/api/v1/tasks/{csv_task['id']}/recurrence").json()["trigger_mode"] == "after_completion"
+9 -8
View File
@@ -376,7 +376,7 @@ def test_folder_and_list_lifecycle(client):
assert client.delete(f"/api/v1/folders/{folder['id']}").status_code == 204
def test_task_search_subtasks_and_recycle_bin(client):
def test_task_subtasks_and_recycle_bin(client):
client = initialized_client(client)
inbox = client.get("/api/v1/lists").json()[0]
parent = client.post(
@@ -392,10 +392,10 @@ def test_task_search_subtasks_and_recycle_bin(client):
assert detail.status_code == 200
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 "tags" not in listed[0]
assert listed[0]["subtasks"][0]["title"] == "比较价格"
listed = client.get("/api/v1/tasks").json()["items"]
parent_row = next(row for row in listed if row["id"] == parent["id"])
assert "tags" not in parent_row
assert parent_row["subtasks"][0]["title"] == "比较价格"
assert client.delete(f"/api/v1/tasks/{parent['id']}").status_code == 204
trash = client.get("/api/v1/trash").json()["items"]
@@ -470,7 +470,7 @@ def test_inbox_is_protected_and_deleted_collections_are_hidden(client):
).json()
assert client.delete(f"/api/v1/lists/{task_list['id']}").status_code == 204
assert all(row["id"] != task_list["id"] for row in client.get("/api/v1/lists").json())
assert client.get("/api/v1/tasks", params={"q": "保留任务"}).json()["items"] == []
assert all(row["id"] != task["id"] for row in client.get("/api/v1/tasks").json()["items"])
assert client.get(f"/api/v1/tasks/{task['id']}").status_code == 404
archived = client.get("/api/v1/lists", params={"archived": True})
assert archived.status_code == 200
@@ -539,8 +539,9 @@ def test_restore_replace_recovers_habits_and_task_links_without_tags(client):
habits = client.get("/api/v1/habits").json()
assert "俯卧撑" in [row["name"] for row in habits]
assert "深蹲" in [row["name"] for row in habits]
listed = client.get("/api/v1/tasks", params={"q": "备份任务"}).json()["items"]
assert "tags" not in listed[0]
listed = client.get("/api/v1/tasks").json()["items"]
backup_row = next(row for row in listed if row["title"] == "备份任务")
assert "tags" not in backup_row
def test_trash_cursor_paginates_more_than_fifty_items(client):
+1 -1
View File
@@ -257,7 +257,7 @@ def test_parent_with_multiple_children_round_trips_in_arbitrary_zip_order(client
"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
"dddddddd-dddd-4ddd-8ddd-dddddddddddd",
}
items = client.get("/api/v1/tasks", params={"q": "tree task"}).json()["items"]
items = client.get("/api/v1/tasks", params={"limit": 100}).json()["items"]
restored_parent = next(item for item in items if item["id"] == parent_id)
assert {child["id"] for child in restored_parent["subtasks"]} == {
"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
+7 -4
View File
@@ -160,7 +160,8 @@ def test_zip_v2_round_trip_includes_history_exception_and_attachment_bytes(clien
json={"preflight_token": preflight.json()["preflight_token"], "mode": "replace"},
)
assert restored.status_code == 200, restored.text
restored_task = client.get("/api/v1/tasks", params={"q": "完整备份任务"}).json()["items"][0]
restored_items = client.get("/api/v1/tasks", params={"limit": 100}).json()["items"]
restored_task = next(item for item in restored_items if item["title"] == "完整备份任务")
restored_attachment = client.get(f"/api/v1/tasks/{restored_task['id']}/attachments").json()[0]
assert client.get(f"/api/v1/attachments/{restored_attachment['id']}").content == attachment_bytes
@@ -643,8 +644,9 @@ def test_restore_handles_child_before_parent_task_order(client):
"/api/v1/backup/restore", json={"preflight_token": token, "mode": "replace"}
)
assert restored.status_code == 200, restored.text
items = client.get("/api/v1/tasks", params={"q": "parent"}).json()["items"]
assert items[0]["subtasks"][0]["title"] == "child"
items = client.get("/api/v1/tasks", params={"limit": 100}).json()["items"]
restored_parent = next(item for item in items if item["title"] == "parent")
assert restored_parent["subtasks"][0]["title"] == "child"
def test_replace_restores_quarantined_files_when_database_write_fails(client, tmp_path, monkeypatch):
@@ -682,7 +684,8 @@ def test_replace_restores_quarantined_files_when_database_write_fails(client, tm
)
assert old_path.read_bytes() == old_bytes
assert client.get("/api/v1/tasks", params={"q": "old"}).json()["items"]
restored_items = client.get("/api/v1/tasks", params={"limit": 100}).json()["items"]
assert any(item["title"] == "old" for item in restored_items)
def test_archive_blob_is_never_read_whole(client, tmp_path, monkeypatch):
+7 -5
View File
@@ -87,7 +87,7 @@ def test_update_memo_validates_title_length_after_trimming(client):
).status_code == 422
def test_list_memos_scopes_searches_orders_paginates_and_builds_excerpt(client):
def test_list_memos_scopes_orders_paginates_and_builds_excerpt(client):
boot(client)
first = client.post(
"/api/v1/memos", json={"title": "Alpha note", "content": " many\n words\tinside "}
@@ -98,7 +98,7 @@ def test_list_memos_scopes_searches_orders_paginates_and_builds_excerpt(client):
third = client.post("/api/v1/memos", json={"title": "Third"}).json()
assert client.delete(f"/api/v1/memos/{third['id']}").status_code == 204
page = client.get("/api/v1/memos", params={"scope": "active", "q": "ALPHA", "page_size": 1})
page = client.get("/api/v1/memos", params={"scope": "active", "page_size": 1})
assert page.status_code == 200
data = page.json()
assert data["total"] == 2
@@ -109,7 +109,7 @@ def test_list_memos_scopes_searches_orders_paginates_and_builds_excerpt(client):
assert "content" not in data["items"][0]
second_page = client.get(
"/api/v1/memos", params={"scope": "active", "q": "alpha", "page": 2, "page_size": 1}
"/api/v1/memos", params={"scope": "active", "page": 2, "page_size": 1}
).json()
assert second_page["items"][0]["id"] == first["id"]
assert second_page["items"][0]["excerpt"] == "many words inside"
@@ -267,11 +267,13 @@ def test_restore_reassigns_foreign_memo_to_current_user(client):
}]
response = client.post("/api/v1/restore?mode=merge", json=exported)
assert response.status_code == 200
imported = client.get("/api/v1/memos", params={"q": "Imported"}).json()["items"][0]
imported_items = client.get("/api/v1/memos", params={"page_size": 100}).json()["items"]
imported = next(item for item in imported_items if item["title"] == "Imported")
assert imported["id"] != foreign_id
assert client.get(f"/api/v1/memos/{imported['id']}").json()["content"] == "owned here"
assert client.post("/api/v1/restore?mode=merge", json=exported).status_code == 200
assert client.get("/api/v1/memos", params={"q": "Imported"}).json()["total"] == 1
memo_items = client.get("/api/v1/memos", params={"page_size": 100}).json()["items"]
assert sum(item["title"] == "Imported" for item in memo_items) == 1
def test_legacy_backup_without_memos_still_restores(client):
+3 -2
View File
@@ -73,7 +73,7 @@ def test_creating_task_with_recurrence_is_atomic(client):
json={"title": "缺少日期", "list_id": inbox["id"], "rrule": "FREQ=DAILY"},
)
assert rejected.status_code == 422
assert client.get("/api/v1/tasks", params={"q": "缺少日期"}).json()["items"] == []
assert all(row["title"] != "缺少日期" for row in client.get("/api/v1/tasks").json()["items"])
def test_custom_recurrence_rejects_invalid_weekdays_month_days_and_until(client):
@@ -123,7 +123,8 @@ def test_export_and_restore_preserve_task_recurrence(client):
restored = client.post("/api/v1/restore?mode=merge", json=exported)
assert restored.status_code == 200
restored_task = client.get("/api/v1/tasks", params={"q": "每周整理"}).json()["items"][0]
restored_items = client.get("/api/v1/tasks", params={"limit": 100}).json()["items"]
restored_task = next(item for item in restored_items if item["title"] == "每周整理")
recurrence = client.get(f"/api/v1/tasks/{restored_task['id']}/recurrence").json()
assert recurrence["rrule"] == "FREQ=WEEKLY"