Deskaid
by ezyang
- codemcp
- e2e
#!/usr/bin/env python3
import os
import shutil
import tempfile
import unittest
from unittest import mock
import pytest
from codemcp.shell import run_command
from codemcp.tools.git_blame import git_blame
from codemcp.tools.git_diff import git_diff
from codemcp.tools.git_log import git_log
from codemcp.tools.git_show import git_show
@pytest.mark.asyncio
class TestGitTools(unittest.TestCase):
"""Test the git tools functionality."""
async def asyncSetUp(self):
# Create a temporary directory
self.temp_dir = tempfile.mkdtemp()
# Initialize a git repository
await run_command(
cmd=["git", "init"], cwd=self.temp_dir, capture_output=True, text=True
)
# Create a sample file
self.sample_file = os.path.join(self.temp_dir, "sample.txt")
with open(self.sample_file, "w") as f:
f.write("Sample content\nLine 2\nLine 3\n")
# Add and commit the file
await run_command(
cmd=["git", "config", "user.name", "Test User"],
cwd=self.temp_dir,
capture_output=True,
text=True,
)
await run_command(
cmd=["git", "config", "user.email", "test@example.com"],
cwd=self.temp_dir,
capture_output=True,
text=True,
)
await run_command(
cmd=["git", "add", "sample.txt"],
cwd=self.temp_dir,
capture_output=True,
text=True,
)
await run_command(
cmd=["git", "commit", "-m", "Initial commit"],
cwd=self.temp_dir,
capture_output=True,
text=True,
)
# Modify the file and create another commit
with open(self.sample_file, "a") as f:
f.write("Line 4\nLine 5\n")
await run_command(
cmd=["git", "add", "sample.txt"],
cwd=self.temp_dir,
capture_output=True,
text=True,
)
await run_command(
cmd=["git", "commit", "-m", "Second commit"],
cwd=self.temp_dir,
capture_output=True,
text=True,
)
async def asyncTearDown(self):
# Clean up the temporary directory
shutil.rmtree(self.temp_dir)
async def test_git_log(self):
"""Test the git_log tool."""
# Test with no arguments
result = await git_log(path=self.temp_dir)
self.assertIn("Initial commit", result["output"])
self.assertIn("Second commit", result["output"])
# Test with arguments
result = await git_log(arguments="--oneline -n 1", path=self.temp_dir)
self.assertIn("Second commit", result["output"])
self.assertNotIn("Initial commit", result["output"])
async def test_git_diff(self):
"""Test the git_diff tool."""
# Create a change but don't commit it
with open(self.sample_file, "a") as f:
f.write("Uncommitted change\n")
# Test with no arguments
result = await git_diff(path=self.temp_dir)
self.assertIn("Uncommitted change", result["output"])
# Test with arguments
result = await git_diff(arguments="HEAD~1 HEAD", path=self.temp_dir)
self.assertIn("Line 4", result["output"])
async def test_git_show(self):
"""Test the git_show tool."""
# Test with no arguments (should show the latest commit)
result = await git_show(path=self.temp_dir)
self.assertIn("Second commit", result["output"])
# Test with arguments
result = await git_show(arguments="HEAD~1", path=self.temp_dir)
self.assertIn("Initial commit", result["output"])
async def test_git_blame(self):
"""Test the git_blame tool."""
# Test with file argument
result = await git_blame(arguments="sample.txt", path=self.temp_dir)
self.assertIn("Test User", result["output"])
self.assertIn("Line 2", result["output"])
# Test with line range
result = await git_blame(arguments="-L 4,5 sample.txt", path=self.temp_dir)
self.assertIn("Line 4", result["output"])
self.assertNotIn("Line 2", result["output"])
async def test_invalid_path(self):
"""Test that tools handle invalid paths."""
with mock.patch("codemcp.git.is_git_repository", return_value=False):
with self.assertRaises(ValueError):
await git_log(path="/invalid/path")
with self.assertRaises(ValueError):
await git_diff(path="/invalid/path")
with self.assertRaises(ValueError):
await git_show(path="/invalid/path")
with self.assertRaises(ValueError):
await git_blame(path="/invalid/path")
async def test_command_failure(self):
"""Test that tools handle command failures."""
# Test with invalid arguments
result = await git_log(arguments="--invalid-option", path=self.temp_dir)
self.assertIn("Error", result["resultForAssistant"])
result = await git_diff(arguments="--invalid-option", path=self.temp_dir)
self.assertIn("Error", result["resultForAssistant"])
result = await git_show(arguments="--invalid-option", path=self.temp_dir)
self.assertIn("Error", result["resultForAssistant"])
result = await git_blame(arguments="--invalid-option", path=self.temp_dir)
self.assertIn("Error", result["resultForAssistant"])