T04: DMS plugin backend — folders + files + preview + OnlyOffice + shares + search + bulk — 106 tests, 97.90% coverage
This commit is contained in:
@@ -0,0 +1,564 @@
|
||||
"""Additional DMS error-path tests to boost coverage above 80%."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.conftest import ORIGIN_HEADER
|
||||
|
||||
PDF_CONTENT = b"%PDF-1.4\n1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n%%EOF"
|
||||
|
||||
|
||||
class TestFolderErrorPaths:
|
||||
"""Error path tests for folder endpoints."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_folder_duplicate_name(self, authed_client):
|
||||
"""POST /folders → 409 duplicate name."""
|
||||
client, _ = authed_client
|
||||
await client.post("/api/v1/dms/folders", json={"name": "Dup"}, headers=ORIGIN_HEADER)
|
||||
resp = await client.post("/api/v1/dms/folders", json={"name": "Dup"}, headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 409
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_folder_parent_not_found(self, authed_client):
|
||||
"""POST /folders → 404 parent not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/folders",
|
||||
json={"name": "Child", "parent_id": str(uuid.uuid4())},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_folder_invalid_parent_id(self, authed_client):
|
||||
"""POST /folders → 400 invalid parent_id."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/folders",
|
||||
json={"name": "Child", "parent_id": "not-a-uuid"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_folders_with_parent_id(self, authed_client):
|
||||
"""GET /folders?parent_id → children of specified parent."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/folders", json={"name": "Root"}, headers=ORIGIN_HEADER
|
||||
)
|
||||
root_id = resp.json()["id"]
|
||||
await client.post(
|
||||
"/api/v1/dms/folders",
|
||||
json={"name": "Child1", "parent_id": root_id},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
await client.post(
|
||||
"/api/v1/dms/folders",
|
||||
json={"name": "Child2", "parent_id": root_id},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
|
||||
resp = await client.get(f"/api/v1/dms/folders?parent_id={root_id}", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 200
|
||||
children = resp.json()
|
||||
assert len(children) == 2
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_list_folders_parent_not_found(self, authed_client):
|
||||
"""GET /folders?parent_id=nonexistent → 404."""
|
||||
client, _ = authed_client
|
||||
resp = await client.get(
|
||||
f"/api/v1/dms/folders?parent_id={uuid.uuid4()}", headers=ORIGIN_HEADER
|
||||
)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_folder_not_found(self, authed_client):
|
||||
"""PATCH /folders/{id} → 404 not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.patch(
|
||||
f"/api/v1/dms/folders/{uuid.uuid4()}",
|
||||
json={"name": "New"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_folder_duplicate_name(self, authed_client):
|
||||
"""PATCH /folders/{id} → 409 duplicate name."""
|
||||
client, _ = authed_client
|
||||
await client.post("/api/v1/dms/folders", json={"name": "A"}, headers=ORIGIN_HEADER)
|
||||
resp = await client.post("/api/v1/dms/folders", json={"name": "B"}, headers=ORIGIN_HEADER)
|
||||
b_id = resp.json()["id"]
|
||||
|
||||
resp = await client.patch(
|
||||
f"/api/v1/dms/folders/{b_id}",
|
||||
json={"name": "A"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 409
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_folder_move_into_self(self, authed_client):
|
||||
"""PATCH /folders/{id} → 400 cannot move into itself."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/folders", json={"name": "Self"}, headers=ORIGIN_HEADER
|
||||
)
|
||||
folder_id = resp.json()["id"]
|
||||
|
||||
resp = await client.patch(
|
||||
f"/api/v1/dms/folders/{folder_id}",
|
||||
json={"parent_id": folder_id},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_folder_move_parent_not_found(self, authed_client):
|
||||
"""PATCH /folders/{id} → 404 parent not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/folders", json={"name": "Move"}, headers=ORIGIN_HEADER
|
||||
)
|
||||
folder_id = resp.json()["id"]
|
||||
|
||||
resp = await client.patch(
|
||||
f"/api/v1/dms/folders/{folder_id}",
|
||||
json={"parent_id": str(uuid.uuid4())},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_folder_cycle_detection(self, authed_client):
|
||||
"""PATCH /folders/{id} → 400 cannot move into descendant."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post("/api/v1/dms/folders", json={"name": "P"}, headers=ORIGIN_HEADER)
|
||||
p_id = resp.json()["id"]
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/folders",
|
||||
json={"name": "C", "parent_id": p_id},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
c_id = resp.json()["id"]
|
||||
|
||||
# Try to move P into C (its own child)
|
||||
resp = await client.patch(
|
||||
f"/api/v1/dms/folders/{p_id}",
|
||||
json={"parent_id": c_id},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_folder_not_found(self, authed_client):
|
||||
"""DELETE /folders/{id} → 404 not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.delete(f"/api/v1/dms/folders/{uuid.uuid4()}", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_folder_invalid_id(self, authed_client):
|
||||
"""DELETE /folders/{id} → 400 invalid id."""
|
||||
client, _ = authed_client
|
||||
resp = await client.delete("/api/v1/dms/folders/not-a-uuid", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 400
|
||||
|
||||
|
||||
class TestFileErrorPaths:
|
||||
"""Error path tests for file endpoints."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_upload_file_folder_not_found(self, authed_client):
|
||||
"""POST /files/upload → 404 folder not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("test.pdf", PDF_CONTENT, "application/pdf")},
|
||||
data={"folder_id": str(uuid.uuid4())},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_file_not_found(self, authed_client):
|
||||
"""GET /files/{id} → 404 not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.get(f"/api/v1/dms/files/{uuid.uuid4()}", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_file_invalid_id(self, authed_client):
|
||||
"""GET /files/{id} → 400 invalid id."""
|
||||
client, _ = authed_client
|
||||
resp = await client.get("/api/v1/dms/files/bad-id", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 400
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_file_not_found(self, authed_client):
|
||||
"""PATCH /files/{id} → 404 not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.patch(
|
||||
f"/api/v1/dms/files/{uuid.uuid4()}",
|
||||
json={"name": "new.pdf"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_file_move_folder_not_found(self, authed_client):
|
||||
"""PATCH /files/{id} → 404 folder not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("test.pdf", PDF_CONTENT, "application/pdf")},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
|
||||
resp = await client.patch(
|
||||
f"/api/v1/dms/files/{file_id}",
|
||||
json={"folder_id": str(uuid.uuid4())},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_file_not_found(self, authed_client):
|
||||
"""DELETE /files/{id} → 404 not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.delete(f"/api/v1/dms/files/{uuid.uuid4()}", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_restore_file_not_found(self, authed_client):
|
||||
"""POST /files/{id}/restore → 404 not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(f"/api/v1/dms/files/{uuid.uuid4()}/restore", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_restore_file_not_deleted(self, authed_client):
|
||||
"""POST /files/{id}/restore → 404 file not in trash."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("active.pdf", PDF_CONTENT, "application/pdf")},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
|
||||
resp = await client.post(f"/api/v1/dms/files/{file_id}/restore", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_preview_file_not_found(self, authed_client):
|
||||
"""GET /files/{id}/preview → 404 not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.get(f"/api/v1/dms/files/{uuid.uuid4()}/preview", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_edit_session_not_found(self, authed_client):
|
||||
"""POST /files/{id}/edit-session → 404 not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
f"/api/v1/dms/files/{uuid.uuid4()}/edit-session", headers=ORIGIN_HEADER
|
||||
)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_edit_session_xlsx(self, authed_client):
|
||||
"""POST /files/{id}/edit-session → 200 for xlsx file."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={
|
||||
"file": (
|
||||
"sheet.xlsx",
|
||||
b"PK\x03\x04",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
)
|
||||
},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
|
||||
resp = await client.post(f"/api/v1/dms/files/{file_id}/edit-session", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["document"]["fileType"] == "xlsx"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_edit_session_pptx(self, authed_client):
|
||||
"""POST /files/{id}/edit-session → 200 for pptx file."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={
|
||||
"file": (
|
||||
"slides.pptx",
|
||||
b"PK\x03\x04",
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
)
|
||||
},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
|
||||
resp = await client.post(f"/api/v1/dms/files/{file_id}/edit-session", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["document"]["fileType"] == "pptx"
|
||||
|
||||
|
||||
class TestShareErrorPaths:
|
||||
"""Error path tests for sharing endpoints."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_share_file_not_found(self, authed_client):
|
||||
"""POST /files/{id}/share → 404 file not found."""
|
||||
client, seed = authed_client
|
||||
viewer_id = str(seed["viewer_a"].id)
|
||||
resp = await client.post(
|
||||
f"/api/v1/dms/files/{uuid.uuid4()}/share",
|
||||
json={"user_ids": [viewer_id], "access_level": "read"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_share_with_invalid_user_id(self, authed_client):
|
||||
"""POST /files/{id}/share → 400 invalid user_id."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("share.pdf", PDF_CONTENT, "application/pdf")},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
|
||||
resp = await client.post(
|
||||
f"/api/v1/dms/files/{file_id}/share",
|
||||
json={"user_ids": ["not-a-uuid"], "access_level": "read"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_share_with_group(self, authed_client):
|
||||
"""POST /files/{id}/share → 200 with group_ids."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("group.pdf", PDF_CONTENT, "application/pdf")},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
|
||||
group_id = str(uuid.uuid4())
|
||||
resp = await client.post(
|
||||
f"/api/v1/dms/files/{file_id}/share",
|
||||
json={"group_ids": [group_id], "access_level": "write"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["count"] == 1
|
||||
assert resp.json()["shared_with"][0]["group_id"] == group_id
|
||||
assert resp.json()["shared_with"][0]["access_level"] == "write"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_share_duplicate_ignored(self, authed_client):
|
||||
"""POST /files/{id}/share → 200, duplicate shares ignored."""
|
||||
client, seed = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("dup.pdf", PDF_CONTENT, "application/pdf")},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
viewer_id = str(seed["viewer_a"].id)
|
||||
|
||||
# Share once
|
||||
await client.post(
|
||||
f"/api/v1/dms/files/{file_id}/share",
|
||||
json={"user_ids": [viewer_id], "access_level": "read"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
# Share again — should be ignored
|
||||
resp = await client.post(
|
||||
f"/api/v1/dms/files/{file_id}/share",
|
||||
json={"user_ids": [viewer_id], "access_level": "read"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["count"] == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_remove_share_group(self, authed_client):
|
||||
"""DELETE /files/{id}/share → 204, group share removed."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("grp.pdf", PDF_CONTENT, "application/pdf")},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
group_id = str(uuid.uuid4())
|
||||
|
||||
await client.post(
|
||||
f"/api/v1/dms/files/{file_id}/share",
|
||||
json={"group_ids": [group_id], "access_level": "read"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
|
||||
resp = await client.request(
|
||||
"DELETE",
|
||||
f"/api/v1/dms/files/{file_id}/share",
|
||||
json={"group_id": group_id},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 204
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_remove_share_invalid_id(self, authed_client):
|
||||
"""DELETE /files/{id}/share → 400 invalid user_id."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("bad.pdf", PDF_CONTENT, "application/pdf")},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
|
||||
resp = await client.request(
|
||||
"DELETE",
|
||||
f"/api/v1/dms/files/{file_id}/share",
|
||||
json={"user_id": "not-a-uuid"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
|
||||
class TestBulkErrorPaths:
|
||||
"""Error path tests for bulk operations."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bulk_move_target_not_found(self, authed_client):
|
||||
"""POST /files/bulk-move → 404 target folder not found."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("f.pdf", PDF_CONTENT, "application/pdf")},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/bulk-move",
|
||||
json={"file_ids": [file_id], "target_folder_id": str(uuid.uuid4())},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bulk_move_to_root(self, authed_client):
|
||||
"""POST /files/bulk-move → 200, move to root (null target)."""
|
||||
client, _ = authed_client
|
||||
# Create folder and upload file to it
|
||||
resp = await client.post("/api/v1/dms/folders", json={"name": "Src"}, headers=ORIGIN_HEADER)
|
||||
folder_id = resp.json()["id"]
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("f.pdf", PDF_CONTENT, "application/pdf")},
|
||||
data={"folder_id": folder_id},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
|
||||
# Move to root (no target_folder_id)
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/bulk-move",
|
||||
json={"file_ids": [file_id]},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["target_folder_id"] is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bulk_move_invalid_file_id(self, authed_client):
|
||||
"""POST /files/bulk-move → 400 invalid file_id."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/bulk-move",
|
||||
json={"file_ids": ["not-a-uuid"]},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bulk_delete_invalid_file_id(self, authed_client):
|
||||
"""POST /files/bulk-delete → 400 invalid file_id."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/bulk-delete",
|
||||
json={"file_ids": ["not-a-uuid"]},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bulk_delete_nonexistent_files(self, authed_client):
|
||||
"""POST /files/bulk-delete → 200, 0 deleted for nonexistent files."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/bulk-delete",
|
||||
json={"file_ids": [str(uuid.uuid4())]},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["deleted"] == 0
|
||||
|
||||
|
||||
class TestSearchEdgeCases:
|
||||
"""Edge case tests for search endpoint."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_no_results(self, authed_client):
|
||||
"""GET /search?q=nonexistent → 200 + empty list."""
|
||||
client, _ = authed_client
|
||||
resp = await client.get("/api/v1/dms/search?q=nonexistent", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json() == []
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_search_excludes_deleted(self, authed_client):
|
||||
"""GET /search → excludes soft-deleted files."""
|
||||
client, _ = authed_client
|
||||
resp = await client.post(
|
||||
"/api/v1/dms/files/upload",
|
||||
files={"file": ("deleteme.pdf", PDF_CONTENT, "application/pdf")},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
file_id = resp.json()["id"]
|
||||
await client.delete(f"/api/v1/dms/files/{file_id}", headers=ORIGIN_HEADER)
|
||||
|
||||
resp = await client.get("/api/v1/dms/search?q=deleteme", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json() == []
|
||||
|
||||
|
||||
class TestSharedWithMeEdgeCases:
|
||||
"""Edge case tests for shared-with-me endpoint."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_shared_with_me_empty(self, authed_client):
|
||||
"""GET /shared-with-me → 200 + empty list for admin (no shares)."""
|
||||
client, _ = authed_client
|
||||
resp = await client.get("/api/v1/dms/shared-with-me", headers=ORIGIN_HEADER)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json() == []
|
||||
Reference in New Issue
Block a user