from __future__ import annotations import asyncio import sys import tempfile import unittest from datetime import datetime, timezone from pathlib import Path import httpx sys.path.insert(0, str(Path(__file__).resolve().parents[3])) from backend.app.dependencies import get_browse_service from backend.app.fs.filesystem_adapter import FilesystemAdapter from backend.app.main import app from backend.app.security.path_guard import PathGuard from backend.app.services.browse_service import BrowseService class BrowseApiGoldenTest(unittest.TestCase): def setUp(self) -> None: self.temp_dir = tempfile.TemporaryDirectory() self.root = Path(self.temp_dir.name) / "root" self.root.mkdir(parents=True, exist_ok=True) folder = self.root / "folder" folder.mkdir() file_path = self.root / "video.mkv" file_path.write_bytes(b"abc") hidden_dir = self.root / ".hidden_dir" hidden_dir.mkdir() hidden_file = self.root / ".secret" hidden_file.write_bytes(b"x") mtime = 1710000000 for path in [folder, file_path, hidden_dir, hidden_file]: Path(path).touch() Path(path).chmod(0o755) import os os.utime(path, (mtime, mtime)) service = BrowseService( path_guard=PathGuard({"storage1": str(self.root)}), filesystem=FilesystemAdapter(), ) async def _override_browse_service() -> BrowseService: return service app.dependency_overrides[get_browse_service] = _override_browse_service def tearDown(self) -> None: app.dependency_overrides.clear() self.temp_dir.cleanup() def _get(self, path: str, show_hidden: str | None = None) -> httpx.Response: async def _run() -> httpx.Response: transport = httpx.ASGITransport(app=app) async with httpx.AsyncClient(transport=transport, base_url="http://testserver") as client: params = {"path": path} if show_hidden is not None: params["show_hidden"] = show_hidden return await client.get("/api/browse", params=params) return asyncio.run(_run()) def test_browse_success_default_hides_hidden_entries(self) -> None: response = self._get("storage1") self.assertEqual(response.status_code, 200) modified = datetime.fromtimestamp(1710000000, tz=timezone.utc).isoformat().replace("+00:00", "Z") expected = { "path": "storage1", "directories": [ { "name": "folder", "path": "storage1/folder", "modified": modified, } ], "files": [ { "name": "video.mkv", "path": "storage1/video.mkv", "size": 3, "modified": modified, } ], } self.assertEqual(response.json(), expected) def test_browse_success_show_hidden_true(self) -> None: response = self._get("storage1", show_hidden="true") self.assertEqual(response.status_code, 200) body = response.json() directory_names = [item["name"] for item in body["directories"]] file_names = [item["name"] for item in body["files"]] self.assertEqual(directory_names, [".hidden_dir", "folder"]) self.assertEqual(file_names, [".secret", "video.mkv"]) if __name__ == "__main__": unittest.main()