Files
headquarter/apps/api/tests/test_git_operations.py
T
alex 3728c245d3 feat(FN-007): implement repository connection API and git operations
- Add GitHubAdapter and GitLabAdapter with URL parsing
- Create provider factory in apps/api/app/git/providers/
- Implement clone, fetch, push in LocalGitOperations
- Add repository_connections router with CRUD and SSH key endpoints
- Create RepositoryConnection schema with validation
- Update models and routers __init__.py for new components
- Add comprehensive tests for git operations
2026-05-16 13:41:37 +02:00

148 lines
4.3 KiB
Python

"""Tests for local Git operations."""
import subprocess
import tempfile
from pathlib import Path
from typing import Any
import pytest
from app.git.operations import LocalGitOperations
@pytest.fixture
def local_git() -> LocalGitOperations:
return LocalGitOperations()
@pytest.fixture
def temp_repo() -> Any:
with tempfile.TemporaryDirectory() as tmpdir:
repo_path = Path(tmpdir) / "repo"
repo_path.mkdir()
subprocess.run(
["git", "init", "--initial-branch=main"],
cwd=repo_path,
capture_output=True,
text=True,
check=True,
)
subprocess.run(
["git", "config", "user.email", "test@example.com"],
cwd=repo_path,
capture_output=True,
text=True,
check=True,
)
subprocess.run(
["git", "config", "user.name", "Test User"],
cwd=repo_path,
capture_output=True,
text=True,
check=True,
)
yield repo_path
def test_clone_invalid_repo_raises(local_git: LocalGitOperations) -> None:
with pytest.raises(RuntimeError, match="Git clone failed"):
local_git.clone("https://example.com/repo.git", Path("/tmp/dest"), "cred-id")
def test_fetch_no_remote_succeeds(local_git: LocalGitOperations, temp_repo: Path) -> None:
local_git.fetch(temp_repo, "cred-id")
def test_push_no_remote_raises(local_git: LocalGitOperations, temp_repo: Path) -> None:
with pytest.raises(RuntimeError, match="Git push failed"):
local_git.push(temp_repo, "cred-id")
def test_get_status_on_non_git_directory_raises(local_git: LocalGitOperations) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
with pytest.raises(RuntimeError, match="Not a git repository"):
local_git.get_status(Path(tmpdir))
def test_get_status_clean_repo(local_git: LocalGitOperations, temp_repo: Path) -> None:
status = local_git.get_status(temp_repo)
assert status["branch"] == "main"
assert status["clean"] is True
assert status["untracked"] == []
assert status["modified"] == []
assert status["staged"] == []
assert status["deleted"] == []
def test_get_status_untracked_file(local_git: LocalGitOperations, temp_repo: Path) -> None:
(temp_repo / "newfile.txt").write_text("hello")
status = local_git.get_status(temp_repo)
assert "newfile.txt" in status["untracked"]
assert status["clean"] is False
def test_get_status_staged_file(local_git: LocalGitOperations, temp_repo: Path) -> None:
file_path = temp_repo / "newfile.txt"
file_path.write_text("hello")
subprocess.run(
["git", "add", "newfile.txt"],
cwd=temp_repo,
capture_output=True,
text=True,
check=True,
)
status = local_git.get_status(temp_repo)
assert "newfile.txt" in status["staged"]
assert status["clean"] is False
def test_get_status_modified_file(local_git: LocalGitOperations, temp_repo: Path) -> None:
file_path = temp_repo / "newfile.txt"
file_path.write_text("hello")
subprocess.run(
["git", "add", "newfile.txt"],
cwd=temp_repo,
capture_output=True,
text=True,
check=True,
)
file_path.write_text("world")
status = local_git.get_status(temp_repo)
assert "newfile.txt" in status["modified"]
assert status["clean"] is False
def test_get_status_deleted_file(local_git: LocalGitOperations, temp_repo: Path) -> None:
file_path = temp_repo / "newfile.txt"
file_path.write_text("hello")
subprocess.run(
["git", "add", "newfile.txt"],
cwd=temp_repo,
capture_output=True,
text=True,
check=True,
)
subprocess.run(
["git", "commit", "-m", "add file"],
cwd=temp_repo,
capture_output=True,
text=True,
check=True,
)
file_path.unlink()
status = local_git.get_status(temp_repo)
assert "newfile.txt" in status["deleted"]
assert status["clean"] is False
def test_get_status_branch_name(local_git: LocalGitOperations, temp_repo: Path) -> None:
subprocess.run(
["git", "checkout", "-b", "feature-branch"],
cwd=temp_repo,
capture_output=True,
text=True,
check=True,
)
status = local_git.get_status(temp_repo)
assert status["branch"] == "feature-branch"