Files
codexpi/tests/test_git.py
CodexPi 995b17a6e2
Some checks are pending
Qualité / tests (push) Waiting to run
feat: publish CodexPi contest snapshot
2026-11-14 20:23:59 +01:00

102 lines
4.0 KiB
Python

import asyncio
import subprocess
from pathlib import Path
from codexpi.commands import CommandResult
from codexpi.git_service import commit, diff, ensure_identity, repository_tree, snapshot, suggest_commit_message
def git(root: Path, *args: str):
subprocess.run(["git", *args], cwd=root, check=True, capture_output=True)
def test_git_snapshot_and_diff(tmp_path: Path):
repo = tmp_path / "repo"
repo.mkdir()
git(repo, "init")
git(repo, "config", "user.email", "test@example.invalid")
git(repo, "config", "user.name", "CodexPi Test")
target = repo / "hello.txt"
target.write_text("hello\n")
git(repo, "add", "hello.txt")
git(repo, "commit", "-m", "initial")
target.write_text("hello\nworld\n")
state = asyncio.run(snapshot(repo))
assert state["is_repository"] is True
assert state["files"][0]["path"] == "hello.txt"
assert state["history"][0]["subject"] == "initial"
assert state["history"][0]["files"] == [{"status": "A", "path": "hello.txt", "old_path": None}]
assert "+world" in asyncio.run(diff(repo))
def test_git_snapshot_supports_repository_without_commits(tmp_path: Path):
repo = tmp_path / "empty-repo"
repo.mkdir()
git(repo, "init")
state = asyncio.run(snapshot(repo))
assert state["is_repository"] is True
assert state["history"] == []
assert state["branch"] in {"main", "master"}
def test_git_snapshot_reports_plain_directory_without_error(tmp_path: Path):
state = asyncio.run(snapshot(tmp_path))
assert state == {"is_repository": False, "branch": None, "files": [], "history": []}
def test_repository_tree_includes_tracked_and_visible_untracked_files(tmp_path: Path):
repo = tmp_path / "tree"
repo.mkdir()
git(repo, "init")
(repo / "src").mkdir()
(repo / "src" / "tracked.py").write_text("print('tracked')\n", encoding="utf-8")
(repo / "README.md").write_text("read me\n", encoding="utf-8")
(repo / "visible.txt").write_text("visible\n", encoding="utf-8")
(repo / "secret.env").write_text("SECRET=value\n", encoding="utf-8")
(repo / ".gitignore").write_text("secret.env\n", encoding="utf-8")
git(repo, "add", "src/tracked.py", "README.md", ".gitignore")
tree = asyncio.run(repository_tree(repo))
assert tree == {
"files": [".gitignore", "README.md", "src/tracked.py", "visible.txt"],
"total": 4,
"truncated": False,
}
def test_git_commit_configures_missing_identity_locally(tmp_path: Path):
repo = tmp_path / "identity"
repo.mkdir()
git(repo, "init")
(repo / "hello.txt").write_text("hello\n", encoding="utf-8")
git(repo, "add", "hello.txt")
asyncio.run(commit(repo, "Premier commit", "Example User"))
name = subprocess.run(["git", "config", "--local", "user.name"], cwd=repo, check=True, capture_output=True, text=True).stdout.strip()
email = subprocess.run(["git", "config", "--local", "user.email"], cwd=repo, check=True, capture_output=True, text=True).stdout.strip()
assert name == "Example User"
assert email == "example-user@codexpi.local"
def test_git_identity_preserves_existing_repository_values(tmp_path: Path):
repo = tmp_path / "existing-identity"
repo.mkdir()
git(repo, "init")
git(repo, "config", "user.name", "Existing Author")
git(repo, "config", "user.email", "existing@example.test")
assert asyncio.run(ensure_identity(repo, "Other User")) == {"name": "Existing Author", "email": "existing@example.test"}
def test_codex_suggests_a_single_line_commit_message(tmp_path: Path, monkeypatch):
calls = 0
async def fake_command(argv, **_kwargs):
nonlocal calls
calls += 1
if calls == 1:
return CommandResult(argv, 0, " M app.py\n", "")
return CommandResult(argv, 0, '{"type":"item.completed","item":{"type":"agent_message","text":"Améliore le flux de commit automatique"}}\n', "")
monkeypatch.setattr("codexpi.git_service.run_command", fake_command)
assert asyncio.run(suggest_commit_message(tmp_path, "codex")) == "Améliore le flux de commit automatique"