(Feat): Initial Commit.

This commit is contained in:
2026-01-05 22:11:58 +00:00
commit b9224dd031
21 changed files with 3259 additions and 0 deletions

160
tests/test_loader.py Normal file
View File

@@ -0,0 +1,160 @@
"""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 == {}