Deskaid

  • e2e
#!/usr/bin/env python3 """Tests for the RunCommand with lint.""" import os import unittest from codemcp.testing import MCPEndToEndTestCase class RunCommandLintTest(MCPEndToEndTestCase): """Test the RunCommand with lint subtool.""" async def test_lint_with_run_subtool(self): """Test that RunCommand with lint commits changes made by linting.""" # Create a file that needs linting unlinted_file_path = os.path.join(self.temp_dir.name, "unlinted.py") unlinted_content = """import math import os import sys from typing import List, Dict, Any def unused_param(x, y): # Unused parameter 'y' that linter would remove return x * 2 def main(): # Unused import # Variables defined but not used unused_var = 42 return True """ with open(unlinted_file_path, "w") as f: f.write(unlinted_content) # Add it to git await self.git_run(["add", unlinted_file_path]) # Commit it await self.git_run(["commit", "-m", "Add unlinted file"]) # Create a simple lint script that simulates ruff linting lint_script_path = os.path.join(self.temp_dir.name, "run_lint.sh") with open(lint_script_path, "w") as f: f.write("""#!/bin/bash # Simple mock linter that fixes linting issues in the unlinted.py file if [ -f unlinted.py ]; then # Replace with properly linted version (removed unused imports and variables) cat > unlinted.py << 'EOF' import math from typing import List, Dict, Any def unused_param(x): # Linter removed unused parameter 'y' return x * 2 def main(): return True EOF echo "Linted unlinted.py" fi """) # Make it executable os.chmod(lint_script_path, 0o755) # Create a codemcp.toml file with lint subtool codemcp_toml_path = os.path.join(self.temp_dir.name, "codemcp.toml") with open(codemcp_toml_path, "w") as f: f.write("""[project] name = "test-project" [commands] lint = ["./run_lint.sh"] """) # Record the current commit hash before linting commit_before = await self.git_run( ["rev-parse", "HEAD"], capture_output=True, text=True ) async with self.create_client_session() as session: # First initialize project to get chat_id init_result_text = await self.call_tool_assert_success( session, "codemcp", { "subtool": "InitProject", "path": self.temp_dir.name, "user_prompt": "Test initialization for lint test", "subject_line": "test: initialize for lint test", "reuse_head_chat_id": False, }, ) # Extract chat_id from the init result chat_id = self.extract_chat_id_from_text(init_result_text) # Call the RunCommand tool with lint command and chat_id result_text = await self.call_tool_assert_success( session, "codemcp", { "subtool": "RunCommand", "path": self.temp_dir.name, "command": "lint", "chat_id": chat_id, }, ) # Verify the success message self.assertIn("Code lint successful", result_text) # Verify the file was linted correctly with open(unlinted_file_path) as f: file_content = f.read() expected_content = """import math from typing import List, Dict, Any def unused_param(x): # Linter removed unused parameter 'y' return x * 2 def main(): return True """ self.assertEqual(file_content, expected_content) # Verify git state shows clean working tree after commit status = await self.git_run(["status"], capture_output=True, text=True) # Verify that the working tree is clean (changes were committed) self.assertExpectedInline( status, """\ On branch main nothing to commit, working tree clean""", ) # Verify that a new commit was created commit_after = await self.git_run( ["rev-parse", "HEAD"], capture_output=True, text=True ) # The commit hash should be different self.assertNotEqual(commit_before, commit_after) # Verify the commit message indicates it was a linting change commit_msg = await self.git_run( ["log", "-1", "--pretty=%B"], capture_output=True, text=True ) self.assertIn("Auto-commit lint changes", commit_msg) if __name__ == "__main__": unittest.main()