-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Expand file tree
/
Copy pathtest_utils.py
More file actions
101 lines (79 loc) · 3.11 KB
/
test_utils.py
File metadata and controls
101 lines (79 loc) · 3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import subprocess
import sys
from pathlib import Path
from typing import Any
import pytest
from mcp.cli.cli import _build_uv_command, _get_npx_command, _parse_file_path # type: ignore[reportPrivateUsage]
@pytest.mark.parametrize(
"spec, expected_obj",
[
("server.py", None),
("foo.py:srv_obj", "srv_obj"),
],
)
def test_parse_file_path_accepts_valid_specs(tmp_path: Path, spec: str, expected_obj: str | None):
"""Should accept valid file specs."""
file = tmp_path / spec.split(":")[0]
file.write_text("x = 1")
path, obj = _parse_file_path(f"{file}:{expected_obj}" if ":" in spec else str(file))
assert path == file.resolve()
assert obj == expected_obj
def test_parse_file_path_missing(tmp_path: Path):
"""Should system exit if a file is missing."""
with pytest.raises(SystemExit):
_parse_file_path(str(tmp_path / "missing.py"))
def test_parse_file_exit_on_dir(tmp_path: Path):
"""Should system exit if a directory is passed"""
dir_path = tmp_path / "dir"
dir_path.mkdir()
with pytest.raises(SystemExit):
_parse_file_path(str(dir_path))
def test_build_uv_command_minimal():
"""Should emit core command when no extras specified."""
cmd = _build_uv_command("foo.py")
assert cmd == ["uv", "run", "--with", "mcp", "mcp", "run", "foo.py"]
def test_build_uv_command_adds_editable_and_packages():
"""Should include --with-editable and every --with pkg in correct order."""
test_path = Path("/pkg")
cmd = _build_uv_command(
"foo.py",
with_editable=test_path,
with_packages=["package1", "package2"],
)
assert cmd == [
"uv",
"run",
"--with",
"mcp",
"--with-editable",
str(test_path), # Use str() to match what the function does
"--with",
"package1",
"--with",
"package2",
"mcp",
"run",
"foo.py",
]
def test_get_npx_unix_like(monkeypatch: pytest.MonkeyPatch):
"""Should return "npx" on unix-like systems."""
monkeypatch.setattr(sys, "platform", "linux")
assert _get_npx_command() == "npx"
def test_get_npx_windows(monkeypatch: pytest.MonkeyPatch):
"""Should return one of the npx candidates on Windows."""
candidates = ["npx.cmd", "npx.exe", "npx"]
def fake_run(cmd: list[str], **kw: Any) -> subprocess.CompletedProcess[bytes]:
if cmd[0] in candidates:
return subprocess.CompletedProcess(cmd, 0)
else: # pragma: no cover
raise subprocess.CalledProcessError(1, cmd[0])
monkeypatch.setattr(sys, "platform", "win32")
monkeypatch.setattr(subprocess, "run", fake_run)
assert _get_npx_command() in candidates
def test_get_npx_returns_none_when_npx_missing(monkeypatch: pytest.MonkeyPatch):
"""Should give None if every candidate fails."""
monkeypatch.setattr(sys, "platform", "win32", raising=False)
def always_fail(*args: Any, **kwargs: Any) -> subprocess.CompletedProcess[bytes]:
raise subprocess.CalledProcessError(1, args[0])
monkeypatch.setattr(subprocess, "run", always_fail)
assert _get_npx_command() is None