161 lines
5.8 KiB
Python
161 lines
5.8 KiB
Python
"""Tests for router loader."""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from fastapi import APIRouter
|
|
|
|
from fastapi_route_loader.loader import RouterLoader
|
|
|
|
|
|
class TestRouterLoader:
|
|
"""Test router loader functionality."""
|
|
|
|
def test_is_router_with_api_router(self):
|
|
router = APIRouter()
|
|
assert RouterLoader._is_router(router) is True
|
|
|
|
def test_is_router_with_non_router(self):
|
|
assert RouterLoader._is_router("not a router") is False
|
|
assert RouterLoader._is_router(123) is False
|
|
assert RouterLoader._is_router(None) is False
|
|
|
|
def test_get_module_path_without_package(self):
|
|
base_path = Path("/app/routers")
|
|
file_path = Path("/app/routers/users/api.py")
|
|
module_path = RouterLoader._get_module_path(file_path, base_path, None)
|
|
assert module_path == "users.api"
|
|
|
|
def test_get_module_path_with_package(self):
|
|
base_path = Path("/app/routers")
|
|
file_path = Path("/app/routers/users/api.py")
|
|
module_path = RouterLoader._get_module_path(file_path, base_path, "myapp")
|
|
assert module_path == "myapp.users.api"
|
|
|
|
def test_get_module_path_single_file(self):
|
|
base_path = Path("/app/routers")
|
|
file_path = Path("/app/routers/api.py")
|
|
module_path = RouterLoader._get_module_path(file_path, base_path, None)
|
|
assert module_path == "api"
|
|
|
|
def test_load_from_module_success(self, tmp_path):
|
|
module_content = '''
|
|
from fastapi import APIRouter
|
|
|
|
router = APIRouter()
|
|
other_router = APIRouter()
|
|
not_a_router = "test"
|
|
'''
|
|
module_file = tmp_path / "test_module.py"
|
|
module_file.write_text(module_content)
|
|
|
|
sys.path.insert(0, str(tmp_path))
|
|
try:
|
|
routers = RouterLoader.load_from_module("test_module")
|
|
assert "router" in routers
|
|
assert "other_router" in routers
|
|
assert "not_a_router" not in routers
|
|
assert isinstance(routers["router"], APIRouter)
|
|
finally:
|
|
sys.path.remove(str(tmp_path))
|
|
if "test_module" in sys.modules:
|
|
del sys.modules["test_module"]
|
|
|
|
def test_load_from_module_import_error(self):
|
|
with pytest.raises(ImportError, match="Failed to import module"):
|
|
RouterLoader.load_from_module("nonexistent_module_xyz")
|
|
|
|
def test_load_from_directory_success(self, tmp_path):
|
|
routers_dir = tmp_path / "routers"
|
|
routers_dir.mkdir()
|
|
|
|
(routers_dir / "__init__.py").write_text("")
|
|
(routers_dir / "users.py").write_text(
|
|
"from fastapi import APIRouter\nuser_router = APIRouter()"
|
|
)
|
|
(routers_dir / "posts.py").write_text(
|
|
"from fastapi import APIRouter\npost_router = APIRouter()"
|
|
)
|
|
(routers_dir / "_private.py").write_text(
|
|
"from fastapi import APIRouter\nprivate_router = APIRouter()"
|
|
)
|
|
|
|
sys.path.insert(0, str(tmp_path))
|
|
try:
|
|
routers = RouterLoader.load_from_directory(routers_dir, "routers")
|
|
assert "users.user_router" in routers
|
|
assert "posts.post_router" in routers
|
|
assert "private.private_router" not in routers
|
|
finally:
|
|
sys.path.remove(str(tmp_path))
|
|
for mod in list(sys.modules.keys()):
|
|
if mod.startswith("routers"):
|
|
del sys.modules[mod]
|
|
|
|
def test_load_from_directory_not_found(self):
|
|
with pytest.raises(FileNotFoundError, match="Directory not found"):
|
|
RouterLoader.load_from_directory("/nonexistent/path")
|
|
|
|
def test_load_from_directory_not_a_directory(self, tmp_path):
|
|
file_path = tmp_path / "not_a_dir.txt"
|
|
file_path.write_text("test")
|
|
|
|
with pytest.raises(NotADirectoryError, match="Not a directory"):
|
|
RouterLoader.load_from_directory(file_path)
|
|
|
|
def test_load_from_directory_nested_structure(self, tmp_path):
|
|
routers_dir = tmp_path / "routers"
|
|
routers_dir.mkdir()
|
|
api_dir = routers_dir / "api"
|
|
api_dir.mkdir()
|
|
v1_dir = api_dir / "v1"
|
|
v1_dir.mkdir()
|
|
|
|
(routers_dir / "__init__.py").write_text("")
|
|
(api_dir / "__init__.py").write_text("")
|
|
(v1_dir / "__init__.py").write_text("")
|
|
(v1_dir / "users.py").write_text(
|
|
"from fastapi import APIRouter\nusers_router = APIRouter()"
|
|
)
|
|
|
|
sys.path.insert(0, str(tmp_path))
|
|
try:
|
|
routers = RouterLoader.load_from_directory(routers_dir, "routers")
|
|
assert "users.users_router" in routers
|
|
finally:
|
|
sys.path.remove(str(tmp_path))
|
|
for mod in list(sys.modules.keys()):
|
|
if mod.startswith("routers"):
|
|
del sys.modules[mod]
|
|
|
|
def test_load_from_directory_with_import_errors(self, tmp_path):
|
|
routers_dir = tmp_path / "routers"
|
|
routers_dir.mkdir()
|
|
|
|
(routers_dir / "__init__.py").write_text("")
|
|
(routers_dir / "good.py").write_text(
|
|
"from fastapi import APIRouter\ngood_router = APIRouter()"
|
|
)
|
|
(routers_dir / "bad.py").write_text(
|
|
"import nonexistent_module\nfrom fastapi import APIRouter\nbad_router = APIRouter()"
|
|
)
|
|
|
|
sys.path.insert(0, str(tmp_path))
|
|
try:
|
|
routers = RouterLoader.load_from_directory(routers_dir, "routers")
|
|
assert "good.good_router" in routers
|
|
assert "bad.bad_router" not in routers
|
|
finally:
|
|
sys.path.remove(str(tmp_path))
|
|
for mod in list(sys.modules.keys()):
|
|
if mod.startswith("routers"):
|
|
del sys.modules[mod]
|
|
|
|
def test_load_from_directory_empty(self, tmp_path):
|
|
routers_dir = tmp_path / "empty_routers"
|
|
routers_dir.mkdir()
|
|
|
|
routers = RouterLoader.load_from_directory(routers_dir)
|
|
assert routers == {}
|