-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_cli.py
More file actions
149 lines (117 loc) · 5.39 KB
/
test_cli.py
File metadata and controls
149 lines (117 loc) · 5.39 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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""Basic CLI tests - help output, command registration, config loading."""
from __future__ import annotations
import json
import sys
from unittest.mock import MagicMock, patch
from typer.testing import CliRunner
# Mock the hyperspell SDK before importing our code
sys.modules.setdefault("hyperspell", type(sys)("hyperspell"))
from hyperspell_cli.config import ( # noqa: E402
DEFAULT_BASE_URL,
clear_config,
load_config,
save_config,
)
from hyperspell_cli.main import app # noqa: E402
runner = CliRunner()
class TestHelpOutput:
def test_main_help(self):
result = runner.invoke(app, ["--help"])
assert result.exit_code == 0
assert "Hyperspell CLI" in result.output
def test_auth_help(self):
result = runner.invoke(app, ["auth", "--help"])
assert result.exit_code == 0
assert "login" in result.output
assert "logout" in result.output
assert "status" in result.output
assert "whoami" in result.output
def test_memories_help(self):
result = runner.invoke(app, ["memories", "--help"])
assert result.exit_code == 0
assert "list" in result.output
assert "add" in result.output
assert "delete" in result.output
def test_search_help(self):
result = runner.invoke(app, ["search", "--help"])
assert result.exit_code == 0
assert "query" in result.output.lower() or "QUERY" in result.output
def test_connections_help(self):
result = runner.invoke(app, ["connections", "--help"])
assert result.exit_code == 0
def test_version_flag(self):
result = runner.invoke(app, ["--version"])
assert result.exit_code == 0
assert "hyperspell-cli" in result.output
class TestCommandRegistration:
def test_top_level_commands(self):
result = runner.invoke(app, ["--help"])
for cmd in ["auth", "memories", "connections", "search"]:
assert cmd in result.output, f"Missing top-level command: {cmd}"
def test_auth_subcommands(self):
result = runner.invoke(app, ["auth", "--help"])
for cmd in ["login", "logout", "status", "whoami"]:
assert cmd in result.output, f"Missing auth subcommand: {cmd}"
def test_memories_subcommands(self):
result = runner.invoke(app, ["memories", "--help"])
for cmd in ["list", "add", "get", "delete", "status"]:
assert cmd in result.output, f"Missing memories subcommand: {cmd}"
class TestConfig:
def test_load_config_missing_file(self, tmp_path):
with patch("hyperspell_cli.config.CONFIG_PATH", tmp_path / "nonexistent.json"):
assert load_config() == {}
def test_save_and_load_config(self, tmp_path):
config_path = tmp_path / "config.json"
with (
patch("hyperspell_cli.config.CONFIG_PATH", config_path),
patch("hyperspell_cli.config.CONFIG_DIR", tmp_path),
):
save_config({"api_key": "test-key", "base_url": "https://example.com"})
cfg = load_config()
assert cfg["api_key"] == "test-key"
assert cfg["base_url"] == "https://example.com"
def test_clear_config(self, tmp_path):
config_path = tmp_path / "config.json"
config_path.write_text("{}")
with patch("hyperspell_cli.config.CONFIG_PATH", config_path):
clear_config()
assert not config_path.exists()
def test_load_config_invalid_json(self, tmp_path):
config_path = tmp_path / "config.json"
config_path.write_text("not json")
with patch("hyperspell_cli.config.CONFIG_PATH", config_path):
assert load_config() == {}
def test_default_base_url(self):
assert DEFAULT_BASE_URL == "https://api.hyperspell.com"
class TestLogoutYesFlag:
def test_logout_requires_confirmation_noninteractive(self):
result = runner.invoke(app, ["auth", "logout"])
assert result.exit_code != 0
def test_logout_yes_flag_skips_confirmation(self, tmp_path):
config_path = tmp_path / "config.json"
config_path.write_text(json.dumps({"api_key": "test"}))
with (
patch("hyperspell_cli.config.CONFIG_PATH", config_path),
patch("hyperspell_cli.commands.auth.clear_config") as mock_clear,
):
runner.invoke(app, ["auth", "logout", "--yes"])
mock_clear.assert_called_once()
class TestDeleteYesFlag:
def test_delete_requires_confirmation_noninteractive(self):
result = runner.invoke(app, ["memories", "delete", "test-source", "test-id"])
assert result.exit_code != 0
def test_delete_yes_flag(self):
with patch("hyperspell_cli.commands.memories.get_sdk_client") as mock_client:
mock_client.return_value.memories.delete.return_value = None
runner.invoke(app, ["memories", "delete", "src", "rid", "--yes"])
mock_client.assert_called()
class TestWhoami:
def test_whoami_json(self):
mock_user = MagicMock()
mock_user.model_dump.return_value = {"email": "test@example.com", "name": "Test User"}
with patch("hyperspell_cli.commands.auth.get_sdk_client") as mock_client:
mock_client.return_value.auth.me.return_value = mock_user
result = runner.invoke(app, ["--json", "auth", "whoami"])
assert result.exit_code == 0
data = json.loads(result.output)
assert data["email"] == "test@example.com"