You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

149 lines
5.6 KiB

import pytest
from sqlalchemy import select
from app.models.entities import Directory
@pytest.mark.anyio
async def test_list_root_directory_children_starts_empty(api_client) -> None:
response = await api_client.get("/api/directories/dir_root/children")
assert response.status_code == 200
payload = response.json()
assert payload["directory"]["id"] == "dir_root"
assert payload["directory"]["name"] == "/"
assert payload["items"] == []
assert payload["next_cursor"] is None
@pytest.mark.anyio
async def test_create_directory_and_list_children(api_client) -> None:
create_response = await api_client.post(
"/api/directories",
json={"parent_id": "dir_root", "name": "photos"},
)
assert create_response.status_code == 201
created_directory = create_response.json()["directory"]
assert created_directory["parent_id"] == "dir_root"
assert created_directory["name"] == "photos"
list_response = await api_client.get("/api/directories/dir_root/children")
assert list_response.status_code == 200
payload = list_response.json()
assert [item["name"] for item in payload["items"]] == ["photos"]
assert payload["items"][0]["kind"] == "directory"
@pytest.mark.anyio
async def test_list_children_includes_directories_before_files(api_client, create_file_metadata) -> None:
create_response = await api_client.post(
"/api/directories",
json={"parent_id": "dir_root", "name": "photos"},
)
assert create_response.status_code == 201
await create_file_metadata(name="movie.mp4", content_hash="hash_movie_mp4")
list_response = await api_client.get("/api/directories/dir_root/children")
assert list_response.status_code == 200
payload = list_response.json()
assert [item["kind"] for item in payload["items"]] == ["directory", "file"]
assert payload["items"][0]["name"] == "photos"
assert payload["items"][1]["name"] == "movie.mp4"
assert payload["items"][1]["mime_type"] == "video/mp4"
assert payload["items"][1]["size_bytes"] == 1048576
@pytest.mark.anyio
async def test_create_directory_requires_existing_parent(api_client) -> None:
response = await api_client.post(
"/api/directories",
json={"parent_id": "dir_missing", "name": "photos"},
)
assert response.status_code == 404
assert response.json()["error"]["code"] == "directory_not_found"
@pytest.mark.anyio
async def test_create_directory_rejects_duplicate_name(api_client) -> None:
first = await api_client.post(
"/api/directories",
json={"parent_id": "dir_root", "name": "photos"},
)
second = await api_client.post(
"/api/directories",
json={"parent_id": "dir_root", "name": "photos"},
)
assert first.status_code == 201
assert second.status_code == 409
assert second.json()["error"]["code"] == "directory_conflict"
@pytest.mark.anyio
async def test_rename_directory(api_client) -> None:
create_response = await api_client.post(
"/api/directories",
json={"parent_id": "dir_root", "name": "photos"},
)
directory_id = create_response.json()["directory"]["id"]
rename_response = await api_client.post(
f"/api/directories/{directory_id}/rename",
json={"name": "images"},
)
assert rename_response.status_code == 200
assert rename_response.json()["directory"]["name"] == "images"
list_response = await api_client.get("/api/directories/dir_root/children")
assert [item["name"] for item in list_response.json()["items"]] == ["images"]
@pytest.mark.anyio
async def test_move_directory_updates_parent_listing_and_descendant_paths(api_client, session_factory) -> None:
parent_a = await api_client.post("/api/directories", json={"parent_id": "dir_root", "name": "a"})
parent_b = await api_client.post("/api/directories", json={"parent_id": "dir_root", "name": "b"})
child = await api_client.post("/api/directories", json={"parent_id": parent_a.json()["directory"]["id"], "name": "child"})
move_response = await api_client.post(
f"/api/directories/{parent_a.json()['directory']['id']}/move",
json={"target_parent_id": parent_b.json()["directory"]["id"]},
)
assert move_response.status_code == 200
root_children = await api_client.get("/api/directories/dir_root/children")
assert [item["name"] for item in root_children.json()["items"]] == ["b"]
b_children = await api_client.get(f"/api/directories/{parent_b.json()['directory']['id']}/children")
assert [item["name"] for item in b_children.json()["items"]] == ["a"]
async with session_factory() as session:
moved_directory = (
await session.execute(select(Directory).where(Directory.id == parent_a.json()["directory"]["id"]))
).scalar_one()
moved_child = (
await session.execute(select(Directory).where(Directory.id == child.json()["directory"]["id"]))
).scalar_one()
assert moved_directory.path_key == "/b/a"
assert moved_child.path_key == "/b/a/child"
@pytest.mark.anyio
async def test_move_directory_rejects_descendant_target(api_client) -> None:
parent = await api_client.post("/api/directories", json={"parent_id": "dir_root", "name": "a"})
child = await api_client.post("/api/directories", json={"parent_id": parent.json()["directory"]["id"], "name": "child"})
move_response = await api_client.post(
f"/api/directories/{parent.json()['directory']['id']}/move",
json={"target_parent_id": child.json()["directory"]["id"]},
)
assert move_response.status_code == 400
assert move_response.json()["error"]["code"] == "validation_error"