Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.

Commit 2848b27

Browse files
committed
fix: readd tests that were added at cli command
1 parent c3eff9c commit 2848b27

File tree

1 file changed

+194
-1
lines changed

1 file changed

+194
-1
lines changed

tests/test_cli.py

Lines changed: 194 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Tests for the server module."""
22

3-
from unittest.mock import MagicMock, patch
3+
from unittest.mock import MagicMock, patch, AsyncMock
44

55
import pytest
66
from fastapi.middleware.cors import CORSMiddleware
@@ -11,6 +11,11 @@
1111
from codegate.pipeline.secrets.manager import SecretsManager
1212
from codegate.providers.registry import ProviderRegistry
1313
from codegate.server import init_app
14+
from src.codegate.cli import UvicornServer
15+
from src.codegate.cli import cli
16+
from src.codegate.codegate_logging import LogLevel, LogFormat
17+
from uvicorn.config import Config as UvicornConfig
18+
from click.testing import CliRunner
1419

1520

1621
@pytest.fixture
@@ -148,3 +153,191 @@ def test_error_handling(test_client: TestClient) -> None:
148153
# Test method not allowed
149154
response = test_client.post("/health") # Health endpoint only allows GET
150155
assert response.status_code == 405
156+
157+
158+
@pytest.fixture
159+
def mock_app():
160+
# Create a simple mock for the ASGI application
161+
return MagicMock()
162+
163+
164+
@pytest.fixture
165+
def uvicorn_config(mock_app):
166+
# Assuming mock_app is defined to simulate ASGI application
167+
return UvicornConfig(app=mock_app, host='localhost', port=8000, log_level='info')
168+
169+
170+
@pytest.fixture
171+
def server_instance(uvicorn_config):
172+
with patch('src.codegate.cli.Server', autospec=True) as mock_server_class:
173+
mock_server_instance = mock_server_class.return_value
174+
mock_server_instance.serve = AsyncMock()
175+
yield UvicornServer(uvicorn_config, mock_server_instance)
176+
177+
178+
@pytest.mark.asyncio
179+
async def test_server_starts_and_runs(server_instance):
180+
await server_instance.serve()
181+
server_instance.server.serve.assert_awaited_once()
182+
183+
184+
@pytest.fixture
185+
def cli_runner():
186+
return CliRunner()
187+
188+
189+
@pytest.fixture
190+
def mock_logging(mocker):
191+
return mocker.patch('your_cli_module.structlog.get_logger')
192+
193+
194+
@pytest.fixture
195+
def mock_setup_logging(mocker):
196+
return mocker.patch('your_cli_module.setup_logging')
197+
198+
199+
def test_serve_default_options(cli_runner):
200+
"""Test serve command with default options."""
201+
# Use patches for run_servers and logging setup
202+
with patch("src.codegate.cli.run_servers") as mock_run, \
203+
patch("src.codegate.cli.structlog.get_logger") as mock_logging, \
204+
patch("src.codegate.cli.setup_logging") as mock_setup_logging:
205+
206+
logger_instance = MagicMock()
207+
mock_logging.return_value = logger_instance
208+
209+
# Invoke the CLI command
210+
result = cli_runner.invoke(cli, ["serve"])
211+
212+
# Basic checks to ensure the command executed successfully
213+
assert result.exit_code == 0
214+
215+
# Check if the logging setup was called with expected defaults
216+
mock_setup_logging.assert_called_once_with(LogLevel.INFO, LogFormat.JSON)
217+
218+
# Check if logging was done correctly
219+
mock_logging.assert_called_with("codegate")
220+
221+
# Validate run_servers was called once
222+
mock_run.assert_called_once()
223+
224+
225+
def test_serve_custom_options(cli_runner):
226+
"""Test serve command with custom options."""
227+
with patch("src.codegate.cli.run_servers") as mock_run, \
228+
patch("src.codegate.cli.structlog.get_logger") as mock_logging, \
229+
patch("src.codegate.cli.setup_logging") as mock_setup_logging:
230+
231+
logger_instance = MagicMock()
232+
mock_logging.return_value = logger_instance
233+
234+
# Invoke the CLI command with custom options
235+
result = cli_runner.invoke(
236+
cli,
237+
[
238+
"serve",
239+
"--port", "8989",
240+
"--host", "localhost",
241+
"--log-level", "DEBUG",
242+
"--log-format", "TEXT",
243+
"--certs-dir", "./custom-certs",
244+
"--ca-cert", "custom-ca.crt",
245+
"--ca-key", "custom-ca.key",
246+
"--server-cert", "custom-server.crt",
247+
"--server-key", "custom-server.key",
248+
],
249+
)
250+
251+
# Check the command executed successfully
252+
assert result.exit_code == 0
253+
254+
# Assert logging setup was called with the provided log level and format
255+
mock_setup_logging.assert_called_once_with(LogLevel.DEBUG, LogFormat.TEXT)
256+
257+
# Assert logger got called with the expected module name
258+
mock_logging.assert_called_with("codegate")
259+
260+
# Validate run_servers was called once
261+
mock_run.assert_called_once()
262+
# Retrieve the actual Config object passed to run_servers
263+
config_arg = mock_run.call_args[0][0] # Assuming Config is the first positional arg
264+
265+
# Define expected values that should be present in the Config object
266+
expected_values = {
267+
"port": 8989,
268+
"host": "localhost",
269+
"log_level": LogLevel.DEBUG,
270+
"log_format": LogFormat.TEXT,
271+
"certs_dir": "./custom-certs",
272+
"ca_cert": "custom-ca.crt",
273+
"ca_key": "custom-ca.key",
274+
"server_cert": "custom-server.crt",
275+
"server_key": "custom-server.key",
276+
}
277+
278+
# Check if Config object attributes match the expected values
279+
for key, expected_value in expected_values.items():
280+
assert getattr(config_arg, key) == expected_value, f"{key} does not match expected value"
281+
282+
283+
def test_serve_invalid_port(cli_runner):
284+
"""Test serve command with invalid port."""
285+
result = cli_runner.invoke(cli, ["serve", "--port", "999999"])
286+
assert result.exit_code == 2 # Typically 2 is used for CLI errors in Click
287+
assert "Port must be between 1 and 65535" in result.output
288+
289+
290+
def test_serve_invalid_log_level(cli_runner):
291+
"""Test serve command with invalid log level."""
292+
result = cli_runner.invoke(cli, ["serve", "--log-level", "INVALID"])
293+
assert result.exit_code == 2
294+
assert "Invalid value for '--log-level'" in result.output
295+
296+
297+
@pytest.fixture
298+
def temp_config_file(tmp_path):
299+
config_path = tmp_path / "config.yaml"
300+
config_path.write_text("""
301+
log_level: DEBUG
302+
log_format: JSON
303+
port: 8989
304+
host: localhost
305+
certs_dir: ./test-certs
306+
""")
307+
return config_path
308+
309+
310+
def test_serve_with_config_file(cli_runner, temp_config_file):
311+
"""Test serve command with config file."""
312+
with patch("src.codegate.cli.run_servers") as mock_run, \
313+
patch("src.codegate.cli.structlog.get_logger") as mock_logging, \
314+
patch("src.codegate.cli.setup_logging") as mock_setup_logging:
315+
316+
logger_instance = MagicMock()
317+
mock_logging.return_value = logger_instance
318+
319+
# Invoke the CLI command with the configuration file
320+
result = cli_runner.invoke(cli, ["serve", "--config", str(temp_config_file)])
321+
322+
# Assertions to ensure the CLI ran successfully
323+
assert result.exit_code == 0
324+
mock_setup_logging.assert_called_once_with(LogLevel.DEBUG, LogFormat.JSON)
325+
mock_logging.assert_called_with("codegate")
326+
327+
# Validate that run_servers was called with the expected configuration
328+
mock_run.assert_called_once()
329+
config_arg = mock_run.call_args[0][0] # Assuming Config object is the first positional argument
330+
331+
# Define expected values based on the temp_config_file content
332+
expected_values = {
333+
"port": 8989,
334+
"host": "localhost",
335+
"log_level": LogLevel.DEBUG,
336+
"log_format": LogFormat.JSON,
337+
"certs_dir": "./test-certs",
338+
}
339+
340+
# Check if passed arguments match the expected values
341+
for key, expected_value in expected_values.items():
342+
assert getattr(config_arg, key) == expected_value, f"{key} does not match expected value"
343+

0 commit comments

Comments
 (0)