Merge remote-tracking branch 'upstream/main' into fix/clink-codex-search-arg
This commit is contained in:
@@ -1 +1 @@
|
||||
# Tests for Zen MCP Server
|
||||
# Tests for PAL MCP Server
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Pytest configuration for Zen MCP Server tests
|
||||
Pytest configuration for PAL MCP Server tests
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
@@ -18,7 +18,7 @@ if str(parent_dir) not in sys.path:
|
||||
import utils.env as env_config # noqa: E402
|
||||
|
||||
# Ensure tests operate with runtime environment rather than .env overrides during imports
|
||||
env_config.reload_env({"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
env_config.reload_env({"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
|
||||
# Set default model to a specific value for tests to avoid auto mode
|
||||
# This prevents all tests from failing due to missing model parameter
|
||||
@@ -187,8 +187,8 @@ def clear_model_restriction_env(monkeypatch):
|
||||
def disable_force_env_override(monkeypatch):
|
||||
"""Default tests to runtime environment visibility unless they explicitly opt in."""
|
||||
|
||||
monkeypatch.setenv("ZEN_MCP_FORCE_ENV_OVERRIDE", "false")
|
||||
env_config.reload_env({"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
monkeypatch.setenv("PAL_MCP_FORCE_ENV_OVERRIDE", "false")
|
||||
env_config.reload_env({"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
monkeypatch.setenv("DEFAULT_MODEL", "gemini-2.5-flash")
|
||||
monkeypatch.setenv("MAX_CONVERSATION_TURNS", "50")
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"temperature": 1.0,
|
||||
"candidateCount": 1,
|
||||
"thinkingConfig": {
|
||||
"thinkingBudget": 10813
|
||||
"thinking_budget": 10813
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"temperature": 0.2,
|
||||
"candidateCount": 1,
|
||||
"thinkingConfig": {
|
||||
"thinkingBudget": 8110
|
||||
"thinking_budget": 8110
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
}
|
||||
],
|
||||
"generationConfig": {
|
||||
"temperature": 0.2,
|
||||
"temperature": 1.0,
|
||||
"candidateCount": 1,
|
||||
"thinkingConfig": {
|
||||
"thinkingBudget": 8110
|
||||
"thinking_budget": 8110
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,12 +73,12 @@ def test_error_listing_respects_env_restrictions(monkeypatch, reset_registry):
|
||||
"AZURE_MODELS_CONFIG_PATH",
|
||||
):
|
||||
monkeypatch.delenv(azure_var, raising=False)
|
||||
monkeypatch.setenv("ZEN_MCP_FORCE_ENV_OVERRIDE", "false")
|
||||
env_config.reload_env({"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
monkeypatch.setenv("PAL_MCP_FORCE_ENV_OVERRIDE", "false")
|
||||
env_config.reload_env({"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
try:
|
||||
import dotenv
|
||||
|
||||
monkeypatch.setattr(dotenv, "dotenv_values", lambda *_args, **_kwargs: {"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
monkeypatch.setattr(dotenv, "dotenv_values", lambda *_args, **_kwargs: {"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
|
||||
@@ -151,7 +151,7 @@ def test_error_listing_without_restrictions_shows_full_catalog(monkeypatch, rese
|
||||
monkeypatch.setenv("OPENAI_API_KEY", "test-openai")
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "test-openrouter")
|
||||
monkeypatch.setenv("XAI_API_KEY", "test-xai")
|
||||
monkeypatch.setenv("ZEN_MCP_FORCE_ENV_OVERRIDE", "false")
|
||||
monkeypatch.setenv("PAL_MCP_FORCE_ENV_OVERRIDE", "false")
|
||||
for azure_var in (
|
||||
"AZURE_OPENAI_API_KEY",
|
||||
"AZURE_OPENAI_ENDPOINT",
|
||||
@@ -159,11 +159,11 @@ def test_error_listing_without_restrictions_shows_full_catalog(monkeypatch, rese
|
||||
"AZURE_MODELS_CONFIG_PATH",
|
||||
):
|
||||
monkeypatch.delenv(azure_var, raising=False)
|
||||
env_config.reload_env({"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
env_config.reload_env({"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
try:
|
||||
import dotenv
|
||||
|
||||
monkeypatch.setattr(dotenv, "dotenv_values", lambda *_args, **_kwargs: {"ZEN_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
monkeypatch.setattr(dotenv, "dotenv_values", lambda *_args, **_kwargs: {"PAL_MCP_FORCE_ENV_OVERRIDE": "false"})
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ CASSETTE_REPLAY_ID = "chat_codegen/gemini25_pro_calculator/mldev"
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.no_mock_provider
|
||||
async def test_chat_codegen_saves_file(monkeypatch, tmp_path):
|
||||
"""Ensure Gemini 2.5 Pro responses create zen_generated.code when code is emitted."""
|
||||
"""Ensure Gemini 2.5 Pro responses create pal_generated.code when code is emitted."""
|
||||
|
||||
CASSETTE_PATH.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
@@ -65,7 +65,7 @@ async def test_chat_codegen_saves_file(monkeypatch, tmp_path):
|
||||
|
||||
working_dir = tmp_path / "codegen"
|
||||
working_dir.mkdir()
|
||||
preexisting = working_dir / "zen_generated.code"
|
||||
preexisting = working_dir / "pal_generated.code"
|
||||
preexisting.write_text("stale contents", encoding="utf-8")
|
||||
|
||||
chat_tool = ChatTool()
|
||||
@@ -102,7 +102,7 @@ async def test_chat_codegen_saves_file(monkeypatch, tmp_path):
|
||||
payload = json.loads(result[0].text)
|
||||
assert payload["status"] in {"success", "continuation_available"}
|
||||
|
||||
artifact_path = working_dir / "zen_generated.code"
|
||||
artifact_path = working_dir / "pal_generated.code"
|
||||
assert artifact_path.exists()
|
||||
saved = artifact_path.read_text()
|
||||
assert "<GENERATED-CODE>" in saved
|
||||
|
||||
@@ -133,7 +133,7 @@ class TestChatTool:
|
||||
assert "Evaluate this perspective" in formatted
|
||||
|
||||
def test_format_response_multiple_generated_code_blocks(self, tmp_path):
|
||||
"""All generated-code blocks should be combined and saved to zen_generated.code."""
|
||||
"""All generated-code blocks should be combined and saved to pal_generated.code."""
|
||||
tool = ChatTool()
|
||||
tool._model_context = SimpleNamespace(capabilities=SimpleNamespace(allow_code_generation=True))
|
||||
|
||||
@@ -148,7 +148,7 @@ class TestChatTool:
|
||||
|
||||
formatted = tool.format_response(response, request)
|
||||
|
||||
saved_path = tmp_path / "zen_generated.code"
|
||||
saved_path = tmp_path / "pal_generated.code"
|
||||
saved_content = saved_path.read_text(encoding="utf-8")
|
||||
|
||||
assert "print('world')" in saved_content
|
||||
@@ -172,7 +172,7 @@ class TestChatTool:
|
||||
|
||||
formatted = tool.format_response(response, request)
|
||||
|
||||
saved_path = tmp_path / "zen_generated.code"
|
||||
saved_path = tmp_path / "pal_generated.code"
|
||||
saved_content = saved_path.read_text(encoding="utf-8")
|
||||
|
||||
assert "print('only-once')" in saved_content
|
||||
@@ -191,7 +191,7 @@ class TestChatTool:
|
||||
|
||||
formatted = tool.format_response(response, request)
|
||||
|
||||
saved_path = tmp_path / "zen_generated.code"
|
||||
saved_path = tmp_path / "pal_generated.code"
|
||||
assert not saved_path.exists()
|
||||
assert "print('oops')" in formatted
|
||||
|
||||
@@ -206,7 +206,7 @@ class TestChatTool:
|
||||
|
||||
formatted = tool.format_response(response, request)
|
||||
|
||||
saved_path = tmp_path / "zen_generated.code"
|
||||
saved_path = tmp_path / "pal_generated.code"
|
||||
assert not saved_path.exists()
|
||||
assert "</GENERATED-CODE> just text" in formatted
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ async def test_clink_gemini_single_digit_sum():
|
||||
assert status in {"success", "continuation_available"}
|
||||
|
||||
content = payload.get("content", "").strip()
|
||||
assert content == "4"
|
||||
# CLI may include additional metadata like <SUMMARY> tags; check first line or that "4" is present
|
||||
first_line = content.split("\n")[0].strip()
|
||||
assert first_line == "4" or "4" in content, f"Expected '4' in response, got: {content[:100]}"
|
||||
|
||||
if status == "continuation_available":
|
||||
offer = payload.get("continuation_offer") or {}
|
||||
|
||||
@@ -22,7 +22,7 @@ class TestDockerClaudeDesktopIntegration:
|
||||
"""Test MCP configuration for direct docker run"""
|
||||
config = {
|
||||
"mcpServers": {
|
||||
"zen-mcp": {
|
||||
"pal-mcp": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
@@ -32,7 +32,7 @@ class TestDockerClaudeDesktopIntegration:
|
||||
"/path/to/.env",
|
||||
"-v",
|
||||
"/path/to/logs:/app/logs",
|
||||
"zen-mcp-server:latest",
|
||||
"pal-mcp-server:latest",
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -40,10 +40,10 @@ class TestDockerClaudeDesktopIntegration:
|
||||
|
||||
# Validate configuration structure
|
||||
assert "mcpServers" in config
|
||||
assert "zen-mcp" in config["mcpServers"]
|
||||
assert config["mcpServers"]["zen-mcp"]["command"] == "docker"
|
||||
assert "pal-mcp" in config["mcpServers"]
|
||||
assert config["mcpServers"]["pal-mcp"]["command"] == "docker"
|
||||
|
||||
args = config["mcpServers"]["zen-mcp"]["args"]
|
||||
args = config["mcpServers"]["pal-mcp"]["args"]
|
||||
assert "run" in args
|
||||
assert "--rm" in args
|
||||
assert "-i" in args
|
||||
@@ -53,27 +53,27 @@ class TestDockerClaudeDesktopIntegration:
|
||||
"""Test MCP configuration for docker-compose run"""
|
||||
config = {
|
||||
"mcpServers": {
|
||||
"zen-mcp": {
|
||||
"pal-mcp": {
|
||||
"command": "docker-compose",
|
||||
"args": ["-f", "/path/to/docker-compose.yml", "run", "--rm", "zen-mcp"],
|
||||
"args": ["-f", "/path/to/docker-compose.yml", "run", "--rm", "pal-mcp"],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Validate configuration structure
|
||||
assert config["mcpServers"]["zen-mcp"]["command"] == "docker-compose"
|
||||
assert config["mcpServers"]["pal-mcp"]["command"] == "docker-compose"
|
||||
|
||||
args = config["mcpServers"]["zen-mcp"]["args"]
|
||||
args = config["mcpServers"]["pal-mcp"]["args"]
|
||||
assert "-f" in args
|
||||
assert "run" in args
|
||||
assert "--rm" in args
|
||||
assert "zen-mcp" in args
|
||||
assert "pal-mcp" in args
|
||||
|
||||
def test_mcp_config_environment_variables(self):
|
||||
"""Test MCP configuration with inline environment variables"""
|
||||
config = {
|
||||
"mcpServers": {
|
||||
"zen-mcp": {
|
||||
"pal-mcp": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
@@ -83,13 +83,13 @@ class TestDockerClaudeDesktopIntegration:
|
||||
"GEMINI_API_KEY=test_key",
|
||||
"-e",
|
||||
"LOG_LEVEL=INFO",
|
||||
"zen-mcp-server:latest",
|
||||
"pal-mcp-server:latest",
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args = config["mcpServers"]["zen-mcp"]["args"]
|
||||
args = config["mcpServers"]["pal-mcp"]["args"]
|
||||
|
||||
# Check that environment variables are properly formatted
|
||||
env_args = [arg for arg in args if arg.startswith("-e")]
|
||||
@@ -103,23 +103,23 @@ class TestDockerClaudeDesktopIntegration:
|
||||
"""Test Windows-specific path formatting"""
|
||||
windows_config = {
|
||||
"mcpServers": {
|
||||
"zen-mcp": {
|
||||
"pal-mcp": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"--rm",
|
||||
"-i",
|
||||
"--env-file",
|
||||
"C:/Users/User/zen-mcp-server/.env",
|
||||
"C:/Users/User/pal-mcp-server/.env",
|
||||
"-v",
|
||||
"C:/Users/User/zen-mcp-server/logs:/app/logs",
|
||||
"zen-mcp-server:latest",
|
||||
"C:/Users/User/pal-mcp-server/logs:/app/logs",
|
||||
"pal-mcp-server:latest",
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args = windows_config["mcpServers"]["zen-mcp"]["args"]
|
||||
args = windows_config["mcpServers"]["pal-mcp"]["args"]
|
||||
|
||||
# Check Windows path format
|
||||
windows_paths = [arg for arg in args if arg.startswith("C:/")]
|
||||
@@ -132,7 +132,7 @@ class TestDockerClaudeDesktopIntegration:
|
||||
"""Test validation of MCP configuration"""
|
||||
# Valid configuration
|
||||
valid_config = {
|
||||
"mcpServers": {"zen-mcp": {"command": "docker", "args": ["run", "--rm", "-i", "zen-mcp-server:latest"]}}
|
||||
"mcpServers": {"pal-mcp": {"command": "docker", "args": ["run", "--rm", "-i", "pal-mcp-server:latest"]}}
|
||||
}
|
||||
|
||||
# Validate JSON serialization
|
||||
@@ -144,19 +144,19 @@ class TestDockerClaudeDesktopIntegration:
|
||||
"""Test that MCP configuration supports stdio communication"""
|
||||
config = {
|
||||
"mcpServers": {
|
||||
"zen-mcp": {
|
||||
"pal-mcp": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"--rm",
|
||||
"-i", # Interactive mode for stdio
|
||||
"zen-mcp-server:latest",
|
||||
"pal-mcp-server:latest",
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args = config["mcpServers"]["zen-mcp"]["args"]
|
||||
args = config["mcpServers"]["pal-mcp"]["args"]
|
||||
|
||||
# Check for interactive mode
|
||||
assert "-i" in args, "Interactive mode required for stdio communication"
|
||||
@@ -168,9 +168,9 @@ class TestDockerClaudeDesktopIntegration:
|
||||
def test_docker_image_reference(self):
|
||||
"""Test that Docker image is properly referenced"""
|
||||
configs = [
|
||||
{"image": "zen-mcp-server:latest"},
|
||||
{"image": "zen-mcp-server:v1.0.0"},
|
||||
{"image": "registry/zen-mcp-server:latest"},
|
||||
{"image": "pal-mcp-server:latest"},
|
||||
{"image": "pal-mcp-server:v1.0.0"},
|
||||
{"image": "registry/pal-mcp-server:latest"},
|
||||
]
|
||||
|
||||
for config in configs:
|
||||
@@ -185,9 +185,9 @@ class TestDockerClaudeDesktopIntegration:
|
||||
"""Create temporary MCP configuration file"""
|
||||
config = {
|
||||
"mcpServers": {
|
||||
"zen-mcp": {
|
||||
"pal-mcp": {
|
||||
"command": "docker",
|
||||
"args": ["run", "--rm", "-i", "--env-file", "/tmp/.env", "zen-mcp-server:latest"],
|
||||
"args": ["run", "--rm", "-i", "--env-file", "/tmp/.env", "pal-mcp-server:latest"],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,7 @@ class TestDockerClaudeDesktopIntegration:
|
||||
config = json.load(f)
|
||||
|
||||
assert "mcpServers" in config
|
||||
assert "zen-mcp" in config["mcpServers"]
|
||||
assert "pal-mcp" in config["mcpServers"]
|
||||
|
||||
def test_environment_file_integration(self):
|
||||
"""Test integration with .env file"""
|
||||
@@ -254,25 +254,25 @@ class TestDockerMCPErrorHandling:
|
||||
# This would test what happens when the image doesn't exist
|
||||
# In practice, Claude Desktop would show an error
|
||||
nonexistent_config = {
|
||||
"mcpServers": {"zen-mcp": {"command": "docker", "args": ["run", "--rm", "-i", "nonexistent:latest"]}}
|
||||
"mcpServers": {"pal-mcp": {"command": "docker", "args": ["run", "--rm", "-i", "nonexistent:latest"]}}
|
||||
}
|
||||
|
||||
# Configuration should be valid even if image doesn't exist
|
||||
assert "zen-mcp" in nonexistent_config["mcpServers"]
|
||||
assert "pal-mcp" in nonexistent_config["mcpServers"]
|
||||
|
||||
def test_invalid_env_file_path(self):
|
||||
"""Test handling of invalid .env file path"""
|
||||
config_with_invalid_env = {
|
||||
"mcpServers": {
|
||||
"zen-mcp": {
|
||||
"pal-mcp": {
|
||||
"command": "docker",
|
||||
"args": ["run", "--rm", "-i", "--env-file", "/nonexistent/.env", "zen-mcp-server:latest"],
|
||||
"args": ["run", "--rm", "-i", "--env-file", "/nonexistent/.env", "pal-mcp-server:latest"],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Configuration structure should still be valid
|
||||
args = config_with_invalid_env["mcpServers"]["zen-mcp"]["args"]
|
||||
args = config_with_invalid_env["mcpServers"]["pal-mcp"]["args"]
|
||||
assert "--env-file" in args
|
||||
|
||||
def test_docker_permission_issues(self):
|
||||
@@ -294,14 +294,14 @@ class TestDockerMCPErrorHandling:
|
||||
"""Test Docker resource limit configurations"""
|
||||
config_with_limits = {
|
||||
"mcpServers": {
|
||||
"zen-mcp": {
|
||||
"pal-mcp": {
|
||||
"command": "docker",
|
||||
"args": ["run", "--rm", "-i", "--memory=512m", "--cpus=1.0", "zen-mcp-server:latest"],
|
||||
"args": ["run", "--rm", "-i", "--memory=512m", "--cpus=1.0", "pal-mcp-server:latest"],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args = config_with_limits["mcpServers"]["zen-mcp"]["args"]
|
||||
args = config_with_limits["mcpServers"]["pal-mcp"]["args"]
|
||||
|
||||
# Check for resource limits
|
||||
memory_limit = any("--memory" in arg for arg in args)
|
||||
|
||||
@@ -83,7 +83,7 @@ class TestDockerCommandValidation:
|
||||
mock_run.return_value.returncode = 0
|
||||
|
||||
# Standard build command
|
||||
build_cmd = ["docker", "build", "-t", "zen-mcp-server:latest", "."]
|
||||
build_cmd = ["docker", "build", "-t", "pal-mcp-server:latest", "."]
|
||||
|
||||
import subprocess
|
||||
|
||||
@@ -105,7 +105,7 @@ class TestDockerCommandValidation:
|
||||
".env",
|
||||
"-v",
|
||||
"logs:/app/logs",
|
||||
"zen-mcp-server:latest",
|
||||
"pal-mcp-server:latest",
|
||||
"python",
|
||||
"server.py",
|
||||
]
|
||||
@@ -128,7 +128,7 @@ class TestDockerCommandValidation:
|
||||
"/path/to/.env",
|
||||
"-v",
|
||||
"/path/to/logs:/app/logs",
|
||||
"zen-mcp-server:latest",
|
||||
"pal-mcp-server:latest",
|
||||
"python",
|
||||
"server.py",
|
||||
]
|
||||
@@ -139,7 +139,7 @@ class TestDockerCommandValidation:
|
||||
assert "--rm" in mcp_cmd # Automatic cleanup
|
||||
assert "-i" in mcp_cmd # Interactive mode
|
||||
assert "--env-file" in mcp_cmd # Environment variables
|
||||
assert "zen-mcp-server:latest" in mcp_cmd # Image
|
||||
assert "pal-mcp-server:latest" in mcp_cmd # Image
|
||||
|
||||
|
||||
class TestIntegrationChecks:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Unit tests for Docker configuration and implementation of Zen MCP Server
|
||||
Unit tests for Docker configuration and implementation of PAL MCP Server
|
||||
|
||||
This module tests:
|
||||
- Docker and MCP configuration
|
||||
@@ -24,7 +24,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
|
||||
class TestDockerConfiguration:
|
||||
"""Tests for Docker configuration of Zen MCP Server"""
|
||||
"""Tests for Docker configuration of PAL MCP Server"""
|
||||
|
||||
def setup_method(self):
|
||||
"""Setup for each test"""
|
||||
@@ -51,7 +51,7 @@ class TestDockerConfiguration:
|
||||
# Basic YAML syntax check
|
||||
content = self.docker_compose_path.read_text()
|
||||
assert "services:" in content, "docker-compose.yml must have services"
|
||||
assert "zen-mcp" in content, "Service zen-mcp must be defined"
|
||||
assert "pal-mcp" in content, "Service pal-mcp must be defined"
|
||||
assert "build:" in content, "Build configuration must be present"
|
||||
|
||||
def test_environment_file_template(self):
|
||||
@@ -80,7 +80,7 @@ class TestDockerCommands:
|
||||
|
||||
# Simulate docker build
|
||||
subprocess.run(
|
||||
["docker", "build", "-t", "zen-mcp-server:latest", str(self.project_root)], capture_output=True, text=True
|
||||
["docker", "build", "-t", "pal-mcp-server:latest", str(self.project_root)], capture_output=True, text=True
|
||||
)
|
||||
|
||||
mock_run.assert_called_once()
|
||||
@@ -100,7 +100,7 @@ class TestDockerCommands:
|
||||
".env",
|
||||
"-v",
|
||||
"logs:/app/logs",
|
||||
"zen-mcp-server:latest",
|
||||
"pal-mcp-server:latest",
|
||||
"python",
|
||||
"server.py",
|
||||
]
|
||||
@@ -111,7 +111,7 @@ class TestDockerCommands:
|
||||
assert "--rm" in cmd, "Must contain --rm for cleanup"
|
||||
assert "-i" in cmd, "Must contain -i for stdio"
|
||||
assert "--env-file" in cmd, "Must contain --env-file"
|
||||
assert "zen-mcp-server:latest" in cmd, "Must reference the image"
|
||||
assert "pal-mcp-server:latest" in cmd, "Must reference the image"
|
||||
|
||||
@patch("subprocess.run")
|
||||
def test_docker_health_check(self, mock_run):
|
||||
@@ -121,7 +121,7 @@ class TestDockerCommands:
|
||||
|
||||
# Simulate health check
|
||||
subprocess.run(
|
||||
["docker", "run", "--rm", "zen-mcp-server:latest", "python", "/usr/local/bin/healthcheck.py"],
|
||||
["docker", "run", "--rm", "pal-mcp-server:latest", "python", "/usr/local/bin/healthcheck.py"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
@@ -187,7 +187,7 @@ class TestMCPIntegration:
|
||||
# Expected MCP configuration
|
||||
expected_config = {
|
||||
"servers": {
|
||||
"zen-docker": {
|
||||
"pal-docker": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
@@ -197,7 +197,7 @@ class TestMCPIntegration:
|
||||
"/path/to/.env",
|
||||
"-v",
|
||||
"/path/to/logs:/app/logs",
|
||||
"zen-mcp-server:latest",
|
||||
"pal-mcp-server:latest",
|
||||
"python",
|
||||
"server.py",
|
||||
],
|
||||
@@ -208,11 +208,11 @@ class TestMCPIntegration:
|
||||
|
||||
# Check structure
|
||||
assert "servers" in expected_config
|
||||
zen_docker = expected_config["servers"]["zen-docker"]
|
||||
assert zen_docker["command"] == "docker"
|
||||
assert "run" in zen_docker["args"]
|
||||
assert "--rm" in zen_docker["args"]
|
||||
assert "-i" in zen_docker["args"]
|
||||
pal_docker = expected_config["servers"]["pal-docker"]
|
||||
assert pal_docker["command"] == "docker"
|
||||
assert "run" in pal_docker["args"]
|
||||
assert "--rm" in pal_docker["args"]
|
||||
assert "-i" in pal_docker["args"]
|
||||
|
||||
def test_stdio_communication_structure(self):
|
||||
"""Test structure of stdio communication"""
|
||||
@@ -279,7 +279,7 @@ class TestDockerPerformance:
|
||||
expected_max_size_mb = 500 # 500MB max
|
||||
|
||||
# In production, we would do:
|
||||
# result = subprocess.run(['docker', 'images', '--format', '{{.Size}}', 'zen-mcp-server:latest'])
|
||||
# result = subprocess.run(['docker', 'images', '--format', '{{.Size}}', 'pal-mcp-server:latest'])
|
||||
# Here we simulate
|
||||
simulated_size = "294MB" # Current observed size
|
||||
|
||||
@@ -346,7 +346,7 @@ LOG_LEVEL=INFO
|
||||
"-i",
|
||||
"--env-file",
|
||||
".env",
|
||||
"zen-mcp-server:latest",
|
||||
"pal-mcp-server:latest",
|
||||
"python",
|
||||
"server.py",
|
||||
]
|
||||
|
||||
@@ -39,7 +39,7 @@ class TestDockerMCPValidation:
|
||||
mock_run.return_value.returncode = 0
|
||||
|
||||
# Standard Docker MCP command
|
||||
cmd = ["docker", "run", "--rm", "-i", "--env-file", ".env", "zen-mcp-server:latest", "python", "server.py"]
|
||||
cmd = ["docker", "run", "--rm", "-i", "--env-file", ".env", "pal-mcp-server:latest", "python", "server.py"]
|
||||
|
||||
subprocess.run(cmd, capture_output=True)
|
||||
mock_run.assert_called_once_with(cmd, capture_output=True)
|
||||
|
||||
@@ -28,18 +28,18 @@ class TestDockerVolumePersistence:
|
||||
content = self.docker_compose_path.read_text()
|
||||
|
||||
# Check for named volume definition
|
||||
assert "zen-mcp-config:" in content, "zen-mcp-config volume must be defined"
|
||||
assert "pal-mcp-config:" in content, "pal-mcp-config volume must be defined"
|
||||
assert "driver: local" in content, "Named volume must use local driver"
|
||||
|
||||
# Check for volume mounts in service
|
||||
assert "./logs:/app/logs" in content, "Logs volume mount required"
|
||||
assert "zen-mcp-config:/app/conf" in content, "Config volume mount required"
|
||||
assert "pal-mcp-config:/app/conf" in content, "Config volume mount required"
|
||||
|
||||
def test_persistent_volume_creation(self):
|
||||
"""Test that persistent volumes are created correctly"""
|
||||
# This test checks that the volume configuration is valid
|
||||
# In a real environment, you might want to test actual volume creation
|
||||
volume_name = "zen-mcp-config"
|
||||
volume_name = "pal-mcp-config"
|
||||
|
||||
# Mock Docker command to check volume exists
|
||||
with patch("subprocess.run") as mock_run:
|
||||
@@ -84,7 +84,7 @@ class TestDockerVolumePersistence:
|
||||
"run",
|
||||
"--rm",
|
||||
"-v",
|
||||
"zen-mcp-config:/data",
|
||||
"pal-mcp-config:/data",
|
||||
"-v",
|
||||
"$(pwd):/backup",
|
||||
"alpine",
|
||||
@@ -97,7 +97,7 @@ class TestDockerVolumePersistence:
|
||||
]
|
||||
|
||||
# Verify command structure is valid
|
||||
assert "zen-mcp-config:/data" in backup_cmd
|
||||
assert "pal-mcp-config:/data" in backup_cmd
|
||||
assert "tar" in backup_cmd
|
||||
assert "czf" in backup_cmd
|
||||
|
||||
@@ -139,7 +139,7 @@ class TestDockerVolumeIntegration:
|
||||
# Verify that docker-compose run inherits volume configuration
|
||||
# This is more of a configuration validation test
|
||||
|
||||
compose_run_cmd = ["docker-compose", "run", "--rm", "zen-mcp"]
|
||||
compose_run_cmd = ["docker-compose", "run", "--rm", "pal-mcp"]
|
||||
|
||||
# The command should work with the existing volume configuration
|
||||
assert "docker-compose" in compose_run_cmd
|
||||
|
||||
@@ -335,7 +335,7 @@ Pour plus de détails sur chaque problème identifié, consultez les recommandat
|
||||
- [ ] Exécuter les tests de régression
|
||||
|
||||
---
|
||||
*Analyse générée automatiquement par MCP Zen* 🤖
|
||||
*Analyse générée automatiquement par MCP PAL* 🤖
|
||||
""",
|
||||
"metadata": {
|
||||
"tool_name": "analyze",
|
||||
@@ -459,13 +459,13 @@ def run_unit_tests():
|
||||
|
||||
def main():
|
||||
"""Main function."""
|
||||
print("🇫🇷 UTF-8 Integration Test - Zen MCP Server")
|
||||
print("🇫🇷 UTF-8 Integration Test - PAL MCP Server")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
run_utf8_integration_tests()
|
||||
print("\n🎉 SUCCESS: All UTF-8 integration tests passed!")
|
||||
print("🚀 Zen MCP server fully supports French localization!")
|
||||
print("🚀 PAL MCP Server fully supports French localization!")
|
||||
return 0
|
||||
|
||||
except AssertionError as e:
|
||||
|
||||
@@ -5,7 +5,7 @@ This test verifies that when using continuation_id without specifying a model,
|
||||
the system correctly retrieves and uses the model from the previous conversation
|
||||
turn instead of defaulting to DEFAULT_MODEL or the custom provider's default.
|
||||
|
||||
Bug: https://github.com/BeehiveInnovations/zen-mcp-server/issues/111
|
||||
Bug: https://github.com/BeehiveInnovations/pal-mcp-server/issues/111
|
||||
"""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
@@ -361,7 +361,7 @@ class TestOpenRouterFunctionality:
|
||||
# Check default headers
|
||||
assert "HTTP-Referer" in provider.DEFAULT_HEADERS
|
||||
assert "X-Title" in provider.DEFAULT_HEADERS
|
||||
assert provider.DEFAULT_HEADERS["X-Title"] == "Zen MCP Server"
|
||||
assert provider.DEFAULT_HEADERS["X-Title"] == "PAL MCP Server"
|
||||
|
||||
def test_openrouter_model_registry_initialized(self):
|
||||
"""Test that model registry is properly initialized."""
|
||||
|
||||
@@ -58,7 +58,7 @@ class TestPipDetectionFix:
|
||||
# Test case for Git Bash on Windows and non-interactive Linux shells
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
# Create mock virtual environment structure
|
||||
venv_path = Path(temp_dir) / ".zen_venv"
|
||||
venv_path = Path(temp_dir) / ".pal_venv"
|
||||
bin_path = venv_path / "bin"
|
||||
bin_path.mkdir(parents=True)
|
||||
|
||||
|
||||
@@ -431,9 +431,16 @@ class UserController:
|
||||
output = json.loads(result[0].text)
|
||||
assert output["status"] in ["success", "continuation_available"]
|
||||
assert "content" in output
|
||||
# Should mention hello or world or greeting in some form
|
||||
# Should mention hello or world or greeting in some form (including French equivalents)
|
||||
content_lower = output["content"].lower()
|
||||
assert "hello" in content_lower or "world" in content_lower or "greeting" in content_lower
|
||||
assert (
|
||||
"hello" in content_lower
|
||||
or "world" in content_lower
|
||||
or "greeting" in content_lower
|
||||
or "bonjour" in content_lower # French: hello
|
||||
or "monde" in content_lower # French: world
|
||||
or "salut" in content_lower # French: greeting
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -101,7 +101,7 @@ class TestServerTools:
|
||||
content = data["content"]
|
||||
|
||||
# Check for expected content in the markdown output
|
||||
assert "# Zen MCP Server Version" in content
|
||||
assert "# PAL MCP Server Version" in content
|
||||
assert "## Server Information" in content
|
||||
assert "## Configuration" in content
|
||||
assert "Current Version" in content
|
||||
|
||||
@@ -237,7 +237,7 @@ def generate_report():
|
||||
|
||||
def test_emoji_preservation(self):
|
||||
"""Test emoji preservation in JSON encoding."""
|
||||
# Emojis used in Zen MCP tools
|
||||
# Emojis used in PAL MCP tools
|
||||
emojis = [
|
||||
"🔴", # Critical
|
||||
"🟠", # High
|
||||
|
||||
@@ -33,7 +33,7 @@ class TestUvxEnvironmentHandling:
|
||||
|
||||
with tempfile.NamedTemporaryFile("w", delete=False) as tmp_env:
|
||||
temp_env_path = Path(tmp_env.name)
|
||||
tmp_env.write("ZEN_MCP_FORCE_ENV_OVERRIDE=false\n")
|
||||
tmp_env.write("PAL_MCP_FORCE_ENV_OVERRIDE=false\n")
|
||||
|
||||
try:
|
||||
importlib.reload(env_config)
|
||||
@@ -82,7 +82,7 @@ class TestUvxEnvironmentHandling:
|
||||
def test_environment_variables_still_work_without_dotenv(self):
|
||||
"""Test that environment variables work even when dotenv is not available."""
|
||||
# Set a test environment variable
|
||||
test_key = "TEST_ZEN_MCP_VAR"
|
||||
test_key = "TEST_PAL_MCP_VAR"
|
||||
test_value = "test_value_123"
|
||||
|
||||
with mock.patch.dict(os.environ, {test_key: test_value}):
|
||||
@@ -133,14 +133,14 @@ class TestUvxProjectConfiguration:
|
||||
|
||||
# Essential fields for uvx
|
||||
assert "name" in project
|
||||
assert project["name"] == "zen-mcp-server"
|
||||
assert project["name"] == "pal-mcp-server"
|
||||
assert "dependencies" in project
|
||||
assert "requires-python" in project
|
||||
|
||||
# Script entry point for uvx
|
||||
assert "scripts" in project
|
||||
assert "zen-mcp-server" in project["scripts"]
|
||||
assert project["scripts"]["zen-mcp-server"] == "server:run"
|
||||
assert "pal-mcp-server" in project["scripts"]
|
||||
assert project["scripts"]["pal-mcp-server"] == "server:run"
|
||||
|
||||
def test_pyproject_dependencies_match_requirements(self):
|
||||
"""Test that pyproject.toml dependencies align with requirements.txt."""
|
||||
|
||||
Reference in New Issue
Block a user