# #region Test.Api.GitGiteaRoutes [C:3] [TYPE Module] [SEMANTICS test,git,gitea,routes] # @BRIEF Unit tests for Gitea-specific Git API routes — list, create, delete repos. # @RELATION BINDS_TO -> [GitGiteaRoutes] # @TEST_EDGE: config_not_found -> 404 # @TEST_EDGE: wrong_provider -> 400 # @TEST_EDGE: unsupported_provider -> 501 import os os.environ.setdefault("DATABASE_URL", "sqlite:///:memory:") os.environ.setdefault("AUTH_DATABASE_URL", "sqlite:///:memory:") os.environ.setdefault("SECRET_KEY", "test-secret-key-for-tests") import sys from pathlib import Path from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi import FastAPI from fastapi.testclient import TestClient _src = str(Path(__file__).resolve().parent.parent.parent / "src") if _src not in sys.path: sys.path.insert(0, _src) def _make_mock_config(provider: str = "GITEA", pat: str = "pat-123"): cfg = MagicMock() cfg.id = "cfg-1" cfg.url = "https://gitea.example.com" cfg.pat = pat cfg.provider = provider return cfg def _make_mock_gitea_repo(name: str = "my-repo") -> dict: return { "name": name, "full_name": f"org/{name}", "private": False, "clone_url": f"https://gitea.example.com/org/{name}.git", "html_url": f"https://gitea.example.com/org/{name}", "ssh_url": f"git@gitea.example.com:org/{name}.git", "default_branch": "main", } def _make_client(overrides: dict | None = None) -> TestClient: from src.api.routes.git._gitea_routes import router from src.api.routes.git._router import router as parent_router from src.core.database import get_db from src.dependencies import get_current_user, has_permission from src.schemas.auth import User, RoleSchema app = FastAPI() app.include_router(parent_router) app.include_router(router) mock_user = User( id="admin-1", username="admin", email="admin@x.com", auth_source="LOCAL", created_at=__import__("datetime").datetime.now(), roles=[RoleSchema(id="r1", name="Admin", description="", permissions=[])], ) defaults = { get_db: lambda: MagicMock(), get_current_user: lambda: mock_user, } if overrides: defaults.update(overrides) for dep, mock_fn in defaults.items(): app.dependency_overrides[dep] = mock_fn return TestClient(app) # ── list_gitea_repositories ── class TestListGiteaRepositories: """GET /config/{config_id}/gitea/repos""" def test_list_success(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config() mock_gs = MagicMock() mock_gs.list_gitea_repositories = AsyncMock(return_value=[_make_mock_gitea_repo()]) with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs): from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.get("/config/cfg-1/gitea/repos") assert resp.status_code == 200 data = resp.json() assert isinstance(data, list) assert data[0]["name"] == "my-repo" def test_list_config_not_found(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = None from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.get("/config/cfg-999/gitea/repos") assert resp.status_code == 404 def test_list_wrong_provider(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="GITHUB") from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.get("/config/cfg-1/gitea/repos") assert resp.status_code == 400 assert "GITEA provider only" in resp.text # ── create_gitea_repository ── class TestCreateGiteaRepository: """POST /config/{config_id}/gitea/repos""" def test_create_success(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config() mock_gs = MagicMock() mock_gs.create_gitea_repository = AsyncMock(return_value=_make_mock_gitea_repo()) with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs): from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.post("/config/cfg-1/gitea/repos", json={ "name": "new-repo", "private": True, "auto_init": True, }) assert resp.status_code == 200 data = resp.json() assert data["name"] == "my-repo" def test_create_wrong_provider(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="GITLAB") from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.post("/config/cfg-1/gitea/repos", json={ "name": "new-repo", "private": True, }) assert resp.status_code == 400 # ── delete_gitea_repository ── class TestDeleteGiteaRepository: """DELETE /config/{config_id}/gitea/repos/{owner}/{repo_name}""" def test_delete_success(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config() mock_gs = MagicMock() mock_gs.delete_gitea_repository = AsyncMock(return_value=None) with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs): from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.delete("/config/cfg-1/gitea/repos/org/my-repo") assert resp.status_code == 200 assert resp.json()["status"] == "success" def test_delete_wrong_provider(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="GITHUB") from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.delete("/config/cfg-1/gitea/repos/org/my-repo") assert resp.status_code == 400 # ── create_remote_repository ── class TestCreateRemoteRepository: """POST /config/{config_id}/repositories""" def test_create_gitea_success(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config() mock_gs = MagicMock() mock_gs.create_gitea_repository = AsyncMock(return_value=_make_mock_gitea_repo()) with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs): from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.post("/config/cfg-1/repositories", json={ "name": "remote-repo", "private": False, }) assert resp.status_code == 200 data = resp.json() assert data["name"] == "my-repo" assert data["provider"] == "GITEA" def test_create_github_success(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="GITHUB") mock_gs = MagicMock() mock_gs.create_github_repository = AsyncMock(return_value=_make_mock_gitea_repo(name="gh-repo")) with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs): from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.post("/config/cfg-1/repositories", json={ "name": "gh-repo", "private": False, }) assert resp.status_code == 200 assert resp.json()["provider"] == "GITHUB" def test_create_gitlab_success(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="GITLAB") mock_gs = MagicMock() mock_gs.create_gitlab_repository = AsyncMock(return_value=_make_mock_gitea_repo(name="gl-repo")) with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs): from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.post("/config/cfg-1/repositories", json={ "name": "gl-repo", "private": False, }) assert resp.status_code == 200 assert resp.json()["provider"] == "GITLAB" def test_create_unsupported_provider(self): mock_db = MagicMock() mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="UNKNOWN") from src.core.database import get_db client = _make_client({get_db: lambda: mock_db}) resp = client.post("/config/cfg-1/repositories", json={ "name": "repo", "private": False, }) assert resp.status_code == 501 # #endregion Test.Api.GitGiteaRoutes