Skip to content

Commit 99302fe

Browse files
author
LittleCoinCoin
committed
test: add environment integration validation tests
Implement 12 regression tests validating corrected environment data structure integration with MCP host configuration system. Test coverage: - EnvironmentData validation with corrected v2 structure - Multi-host configuration validation across different host types - PackageHostConfiguration validation with server config integration - EnvironmentPackageEntry validation with inheritance patterns - Invalid host name rejection with supported host validation - Invalid package name format validation with proper error messages - MCP package extraction from environment data - Serialization roundtrip testing with datetime handling - Single-server-per-package constraint enforcement - JSON serialization compatibility for API integration - MCPHostType enum validation with all supported host types - Host type validation error handling for invalid values Tests validate the corrected environment data structure that enforces realistic single-server-per-package constraints, replacing the previous multiple-servers-per-package model. Demonstrates proper integration between environment management and MCP host configuration systems with comprehensive validation of data model relationships.
1 parent 502ab4c commit 99302fe

File tree

1 file changed

+281
-0
lines changed

1 file changed

+281
-0
lines changed
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
"""
2+
Test suite for MCP environment integration.
3+
4+
This module tests the integration between environment data and MCP host configuration
5+
with the corrected data structure.
6+
"""
7+
8+
import unittest
9+
import sys
10+
from pathlib import Path
11+
from datetime import datetime
12+
13+
# Add the parent directory to the path to import wobble
14+
sys.path.insert(0, str(Path(__file__).parent.parent))
15+
16+
try:
17+
from wobble.decorators import regression_test, integration_test
18+
except ImportError:
19+
# Fallback decorators if wobble is not available
20+
def regression_test(func):
21+
return func
22+
23+
def integration_test(scope="component"):
24+
def decorator(func):
25+
return func
26+
return decorator
27+
28+
from test_data_utils import MCPHostConfigTestDataLoader
29+
from hatch.mcp_host_config.models import (
30+
MCPServerConfig, EnvironmentData, EnvironmentPackageEntry,
31+
PackageHostConfiguration, MCPHostType
32+
)
33+
34+
35+
class TestMCPEnvironmentIntegration(unittest.TestCase):
36+
"""Test suite for MCP environment integration with corrected structure."""
37+
38+
def setUp(self):
39+
"""Set up test environment."""
40+
self.test_data_loader = MCPHostConfigTestDataLoader()
41+
42+
@regression_test
43+
def test_environment_data_validation_success(self):
44+
"""Test successful environment data validation."""
45+
env_data = self.test_data_loader.load_corrected_environment_data("simple")
46+
environment = EnvironmentData(**env_data)
47+
48+
self.assertEqual(environment.name, "test_environment")
49+
self.assertEqual(len(environment.packages), 1)
50+
51+
package = environment.packages[0]
52+
self.assertEqual(package.name, "weather-toolkit")
53+
self.assertEqual(package.version, "1.0.0")
54+
self.assertIn("claude-desktop", package.configured_hosts)
55+
56+
host_config = package.configured_hosts["claude-desktop"]
57+
self.assertIsInstance(host_config, PackageHostConfiguration)
58+
self.assertIsInstance(host_config.server_config, MCPServerConfig)
59+
60+
@regression_test
61+
def test_environment_data_multi_host_validation(self):
62+
"""Test environment data validation with multiple hosts."""
63+
env_data = self.test_data_loader.load_corrected_environment_data("multi_host")
64+
environment = EnvironmentData(**env_data)
65+
66+
self.assertEqual(environment.name, "multi_host_environment")
67+
self.assertEqual(len(environment.packages), 1)
68+
69+
package = environment.packages[0]
70+
self.assertEqual(package.name, "file-manager")
71+
self.assertEqual(len(package.configured_hosts), 2)
72+
self.assertIn("claude-desktop", package.configured_hosts)
73+
self.assertIn("cursor", package.configured_hosts)
74+
75+
# Verify both host configurations
76+
claude_config = package.configured_hosts["claude-desktop"]
77+
cursor_config = package.configured_hosts["cursor"]
78+
79+
self.assertIsInstance(claude_config, PackageHostConfiguration)
80+
self.assertIsInstance(cursor_config, PackageHostConfiguration)
81+
82+
# Verify server configurations are different for different hosts
83+
self.assertEqual(claude_config.server_config.command, "/usr/local/bin/python")
84+
self.assertEqual(cursor_config.server_config.command, "python")
85+
86+
@regression_test
87+
def test_package_host_configuration_validation(self):
88+
"""Test package host configuration validation."""
89+
server_config_data = self.test_data_loader.load_mcp_server_config("local")
90+
server_config = MCPServerConfig(**server_config_data)
91+
92+
host_config = PackageHostConfiguration(
93+
config_path="~/test/config.json",
94+
configured_at=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
95+
last_synced=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
96+
server_config=server_config
97+
)
98+
99+
self.assertEqual(host_config.config_path, "~/test/config.json")
100+
self.assertIsInstance(host_config.server_config, MCPServerConfig)
101+
self.assertEqual(host_config.server_config.command, "python")
102+
self.assertEqual(len(host_config.server_config.args), 3)
103+
104+
@regression_test
105+
def test_environment_package_entry_validation_success(self):
106+
"""Test successful environment package entry validation."""
107+
server_config_data = self.test_data_loader.load_mcp_server_config("local")
108+
server_config = MCPServerConfig(**server_config_data)
109+
110+
host_config = PackageHostConfiguration(
111+
config_path="~/test/config.json",
112+
configured_at=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
113+
last_synced=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
114+
server_config=server_config
115+
)
116+
117+
package = EnvironmentPackageEntry(
118+
name="test-package",
119+
version="1.0.0",
120+
type="hatch",
121+
source="github:user/test-package",
122+
installed_at=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
123+
configured_hosts={"claude-desktop": host_config}
124+
)
125+
126+
self.assertEqual(package.name, "test-package")
127+
self.assertEqual(package.version, "1.0.0")
128+
self.assertEqual(package.type, "hatch")
129+
self.assertEqual(len(package.configured_hosts), 1)
130+
self.assertIn("claude-desktop", package.configured_hosts)
131+
132+
@regression_test
133+
def test_environment_package_entry_invalid_host_name(self):
134+
"""Test environment package entry validation with invalid host name."""
135+
server_config_data = self.test_data_loader.load_mcp_server_config("local")
136+
server_config = MCPServerConfig(**server_config_data)
137+
138+
host_config = PackageHostConfiguration(
139+
config_path="~/test/config.json",
140+
configured_at=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
141+
last_synced=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
142+
server_config=server_config
143+
)
144+
145+
with self.assertRaises(Exception) as context:
146+
EnvironmentPackageEntry(
147+
name="test-package",
148+
version="1.0.0",
149+
type="hatch",
150+
source="github:user/test-package",
151+
installed_at=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
152+
configured_hosts={"invalid-host": host_config} # Invalid host name
153+
)
154+
155+
self.assertIn("Unsupported host", str(context.exception))
156+
157+
@regression_test
158+
def test_environment_package_entry_invalid_package_name(self):
159+
"""Test environment package entry validation with invalid package name."""
160+
server_config_data = self.test_data_loader.load_mcp_server_config("local")
161+
server_config = MCPServerConfig(**server_config_data)
162+
163+
host_config = PackageHostConfiguration(
164+
config_path="~/test/config.json",
165+
configured_at=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
166+
last_synced=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
167+
server_config=server_config
168+
)
169+
170+
with self.assertRaises(Exception) as context:
171+
EnvironmentPackageEntry(
172+
name="invalid@package!name", # Invalid characters
173+
version="1.0.0",
174+
type="hatch",
175+
source="github:user/test-package",
176+
installed_at=datetime.fromisoformat("2025-09-21T10:00:00.000000"),
177+
configured_hosts={"claude-desktop": host_config}
178+
)
179+
180+
self.assertIn("Invalid package name format", str(context.exception))
181+
182+
@regression_test
183+
def test_environment_data_get_mcp_packages(self):
184+
"""Test getting MCP packages from environment data."""
185+
env_data = self.test_data_loader.load_corrected_environment_data("multi_host")
186+
environment = EnvironmentData(**env_data)
187+
188+
mcp_packages = environment.get_mcp_packages()
189+
190+
self.assertEqual(len(mcp_packages), 1)
191+
self.assertEqual(mcp_packages[0].name, "file-manager")
192+
self.assertEqual(len(mcp_packages[0].configured_hosts), 2)
193+
194+
@regression_test
195+
def test_environment_data_serialization_roundtrip(self):
196+
"""Test environment data serialization and deserialization."""
197+
env_data = self.test_data_loader.load_corrected_environment_data("simple")
198+
environment = EnvironmentData(**env_data)
199+
200+
# Serialize and deserialize
201+
serialized = environment.model_dump()
202+
roundtrip_environment = EnvironmentData(**serialized)
203+
204+
self.assertEqual(environment.name, roundtrip_environment.name)
205+
self.assertEqual(len(environment.packages), len(roundtrip_environment.packages))
206+
207+
original_package = environment.packages[0]
208+
roundtrip_package = roundtrip_environment.packages[0]
209+
210+
self.assertEqual(original_package.name, roundtrip_package.name)
211+
self.assertEqual(original_package.version, roundtrip_package.version)
212+
self.assertEqual(len(original_package.configured_hosts), len(roundtrip_package.configured_hosts))
213+
214+
# Verify host configuration roundtrip
215+
original_host_config = original_package.configured_hosts["claude-desktop"]
216+
roundtrip_host_config = roundtrip_package.configured_hosts["claude-desktop"]
217+
218+
self.assertEqual(original_host_config.config_path, roundtrip_host_config.config_path)
219+
self.assertEqual(original_host_config.server_config.command, roundtrip_host_config.server_config.command)
220+
221+
@regression_test
222+
def test_corrected_environment_structure_single_server_per_package(self):
223+
"""Test that corrected environment structure enforces single server per package."""
224+
env_data = self.test_data_loader.load_corrected_environment_data("simple")
225+
environment = EnvironmentData(**env_data)
226+
227+
# Verify single server per package constraint
228+
for package in environment.packages:
229+
# Each package should have one server configuration per host
230+
for host_name, host_config in package.configured_hosts.items():
231+
self.assertIsInstance(host_config, PackageHostConfiguration)
232+
self.assertIsInstance(host_config.server_config, MCPServerConfig)
233+
234+
# The server configuration should be for this specific package
235+
# (In real usage, the server would be the package's MCP server)
236+
237+
@regression_test
238+
def test_environment_data_json_serialization(self):
239+
"""Test JSON serialization compatibility."""
240+
import json
241+
242+
env_data = self.test_data_loader.load_corrected_environment_data("simple")
243+
environment = EnvironmentData(**env_data)
244+
245+
# Test JSON serialization
246+
json_str = environment.model_dump_json()
247+
self.assertIsInstance(json_str, str)
248+
249+
# Test JSON deserialization
250+
parsed_data = json.loads(json_str)
251+
roundtrip_environment = EnvironmentData(**parsed_data)
252+
253+
self.assertEqual(environment.name, roundtrip_environment.name)
254+
self.assertEqual(len(environment.packages), len(roundtrip_environment.packages))
255+
256+
257+
class TestMCPHostTypeIntegration(unittest.TestCase):
258+
"""Test suite for MCP host type integration."""
259+
260+
@regression_test
261+
def test_mcp_host_type_enum_values(self):
262+
"""Test MCP host type enum values."""
263+
# Verify all expected host types are available
264+
expected_hosts = [
265+
"claude-desktop", "claude-code", "vscode",
266+
"cursor", "lmstudio", "gemini"
267+
]
268+
269+
for host_name in expected_hosts:
270+
host_type = MCPHostType(host_name)
271+
self.assertEqual(host_type.value, host_name)
272+
273+
@regression_test
274+
def test_mcp_host_type_invalid_value(self):
275+
"""Test MCP host type with invalid value."""
276+
with self.assertRaises(ValueError):
277+
MCPHostType("invalid-host")
278+
279+
280+
if __name__ == '__main__':
281+
unittest.main()

0 commit comments

Comments
 (0)