summaryrefslogtreecommitdiff
path: root/servers/gitlab_glab/tests
diff options
context:
space:
mode:
authorDawid Rycerz <dawid@rycerz.xyz>2025-05-28 15:27:57 +0200
committerDawid Rycerz <dawid@rycerz.xyz>2025-05-28 15:27:57 +0200
commit0b819edceb307ce2f8ba6d58b37a86329b7d6ec0 (patch)
treef8bc71742a93cd3cb6baa55ce81d14ad42c42720 /servers/gitlab_glab/tests
parenta56a1ea5fa18c28d2fc3d42bfa780c026ce9b52d (diff)
feat(gitlab_glab): add merge request diff functionality with large diff mitigation
- Add get_mr_diff method to GitLabServer class with support for all glab mr diff options - Implement smart large diff handling that saves diffs > 100KB to temporary files - Add comprehensive test coverage (7 new tests) achieving 95% coverage - Support for MR ID/branch, color options, raw format, and repository selection - Include proper error handling and logging - Update README with usage examples and documentation - Follow project coding standards with type hints and docstrings Resolves large diff handling for LLM consumption while preserving full diff access.
Diffstat (limited to 'servers/gitlab_glab/tests')
-rw-r--r--servers/gitlab_glab/tests/test_integration.py3
-rw-r--r--servers/gitlab_glab/tests/test_server.py177
2 files changed, 179 insertions, 1 deletions
diff --git a/servers/gitlab_glab/tests/test_integration.py b/servers/gitlab_glab/tests/test_integration.py
index 5d7eed5..b7d1005 100644
--- a/servers/gitlab_glab/tests/test_integration.py
+++ b/servers/gitlab_glab/tests/test_integration.py
@@ -28,7 +28,8 @@ class TestIntegration:
# - find_project
# - search_issues
# - create_issue
- assert mock_server.tool.call_count == 4
+ # - get_mr_diff
+ assert mock_server.tool.call_count == 5
# Verify that the tool decorator was called with functions that have
# working_directory parameter. We can't directly access the decorated functions
diff --git a/servers/gitlab_glab/tests/test_server.py b/servers/gitlab_glab/tests/test_server.py
index ab93026..a7e74a4 100644
--- a/servers/gitlab_glab/tests/test_server.py
+++ b/servers/gitlab_glab/tests/test_server.py
@@ -585,3 +585,180 @@ class TestGitLabServer:
# Verify the number of calls
assert mock_run.call_count == len(working_dirs)
+
+ @patch.object(GitLabServer, "execute_glab_command")
+ def test_get_mr_diff_success_small(self, mock_execute: MagicMock) -> None:
+ """Test successful MR diff retrieval with small diff."""
+ # Mock successful command execution with small diff
+ diff_content = """diff --git a/file.txt b/file.txt
+index 1234567..abcdefg 100644
+--- a/file.txt
++++ b/file.txt
+@@ -1,3 +1,4 @@
+ line 1
+ line 2
++new line
+ line 3"""
+ mock_execute.return_value = (True, diff_content)
+
+ server = GitLabServer()
+ working_dir = "/test/directory"
+ result = server.get_mr_diff(
+ working_directory=working_dir,
+ mr_id="123",
+ color="never",
+ raw=False,
+ repo="group/project",
+ )
+
+ assert "diff" in result
+ assert result["diff"] == diff_content
+ assert result["size_kb"] < 1
+ assert result["temp_file_path"] is None
+
+ # Verify command was called with correct arguments
+ mock_execute.assert_called_once_with(
+ ["mr", "diff", "123", "--color", "never", "-R", "group/project"],
+ working_dir,
+ )
+
+ @patch.object(GitLabServer, "execute_glab_command")
+ def test_get_mr_diff_success_current_branch(self, mock_execute: MagicMock) -> None:
+ """Test successful MR diff retrieval for current branch."""
+ diff_content = "diff content"
+ mock_execute.return_value = (True, diff_content)
+
+ server = GitLabServer()
+ working_dir = "/test/directory"
+ result = server.get_mr_diff(working_directory=working_dir)
+
+ assert "diff" in result
+ assert result["diff"] == diff_content
+ assert result["temp_file_path"] is None
+
+ # Verify command was called without MR ID
+ mock_execute.assert_called_once_with(
+ ["mr", "diff", "--color", "never"],
+ working_dir,
+ )
+
+ @patch.object(GitLabServer, "execute_glab_command")
+ def test_get_mr_diff_with_raw_option(self, mock_execute: MagicMock) -> None:
+ """Test MR diff retrieval with raw option."""
+ diff_content = "raw diff content"
+ mock_execute.return_value = (True, diff_content)
+
+ server = GitLabServer()
+ working_dir = "/test/directory"
+ result = server.get_mr_diff(
+ working_directory=working_dir,
+ mr_id="branch-name",
+ color="auto",
+ raw=True,
+ )
+
+ assert "diff" in result
+ assert result["diff"] == diff_content
+
+ # Verify command was called with raw option
+ mock_execute.assert_called_once_with(
+ ["mr", "diff", "branch-name", "--color", "auto", "--raw"],
+ working_dir,
+ )
+
+ @patch("tempfile.NamedTemporaryFile")
+ @patch.object(GitLabServer, "execute_glab_command")
+ def test_get_mr_diff_large_diff_temp_file(
+ self, mock_execute: MagicMock, mock_temp_file: MagicMock
+ ) -> None:
+ """Test MR diff retrieval with large diff that gets saved to temp file."""
+ # Create a large diff content (over 100KB)
+ large_diff = "x" * (101 * 1024) # 101 KB
+ mock_execute.return_value = (True, large_diff)
+
+ # Mock temporary file
+ mock_file = MagicMock()
+ mock_file.name = "/tmp/mr_diff_12345.diff"
+ mock_temp_file.return_value.__enter__.return_value = mock_file
+
+ server = GitLabServer()
+ working_dir = "/test/directory"
+ result = server.get_mr_diff(
+ working_directory=working_dir,
+ mr_id="123",
+ max_size_kb=100,
+ )
+
+ assert result["diff_too_large"] is True
+ assert result["size_kb"] > 100
+ assert result["max_size_kb"] == 100
+ assert result["temp_file_path"] == "/tmp/mr_diff_12345.diff"
+ assert "message" in result
+
+ # Verify temp file was created with correct parameters
+ mock_temp_file.assert_called_once_with(
+ mode='w',
+ suffix='.diff',
+ prefix='mr_diff_',
+ delete=False,
+ encoding='utf-8'
+ )
+ mock_file.write.assert_called_once_with(large_diff)
+
+ @patch("tempfile.NamedTemporaryFile")
+ @patch.object(GitLabServer, "execute_glab_command")
+ def test_get_mr_diff_large_diff_temp_file_error(
+ self, mock_execute: MagicMock, mock_temp_file: MagicMock
+ ) -> None:
+ """Test MR diff retrieval with large diff and temp file creation error."""
+ # Create a large diff content
+ large_diff = "x" * (101 * 1024) # 101 KB
+ mock_execute.return_value = (True, large_diff)
+
+ # Mock temporary file creation error
+ mock_temp_file.side_effect = Exception("Permission denied")
+
+ server = GitLabServer()
+ working_dir = "/test/directory"
+ result = server.get_mr_diff(
+ working_directory=working_dir,
+ mr_id="123",
+ max_size_kb=100,
+ )
+
+ assert "error" in result
+ assert "too large" in result["error"]
+ assert "Permission denied" in result["error"]
+
+ @patch.object(GitLabServer, "execute_glab_command")
+ def test_get_mr_diff_command_failure(self, mock_execute: MagicMock) -> None:
+ """Test MR diff retrieval with command failure."""
+ mock_execute.return_value = (False, {"error": "MR not found"})
+
+ server = GitLabServer()
+ working_dir = "/test/directory"
+ result = server.get_mr_diff(working_directory=working_dir, mr_id="999")
+
+ assert "error" in result
+ assert result["error"] == "MR not found"
+
+ @patch.object(GitLabServer, "execute_glab_command")
+ def test_get_mr_diff_invalid_color_option(self, mock_execute: MagicMock) -> None:
+ """Test MR diff with invalid color option skips color parameter."""
+ diff_content = "diff content"
+ mock_execute.return_value = (True, diff_content)
+
+ server = GitLabServer()
+ working_dir = "/test/directory"
+ result = server.get_mr_diff(
+ working_directory=working_dir,
+ mr_id="123",
+ color="invalid", # Invalid color option
+ )
+
+ assert "diff" in result
+ # Invalid color options should be filtered out, only valid ones are added
+ mock_execute.assert_called_once_with(
+ ["mr", "diff", "123"],
+ working_dir,
+ )