Skip to content

Commit 0e15301

Browse files
LittleCoinCoinLittleCoinCoin
authored andcommitted
test(codex): add comprehensive CLI argument tests
Add 6 tests for Codex CLI arguments in TestAllCodexArguments class: 1. test_all_codex_arguments_accepted - Tests all 10 Codex fields together - Verifies MCPServerConfigCodex instance creation - Validates all field values 2. test_codex_env_vars_list - Tests multiple env_vars values - Verifies list handling with action='append' 3. test_codex_env_header_parsing - Tests KEY=ENV_VAR format parsing - Verifies dict creation from list of KEY=VALUE pairs 4. test_codex_timeout_fields - Tests integer timeout fields - Verifies type=int handling 5. test_codex_enabled_flag - Tests boolean flag - Verifies action='store_true' behavior 6. test_codex_reuses_shared_arguments - Tests shared arguments work for Codex - Verifies cwd, include-tools, exclude-tools, header All tests follow existing patterns from Gemini/Kiro tests and use wobble.decorators.regression_test decorator.
1 parent 7c5e2cb commit 0e15301

File tree

1 file changed

+201
-1
lines changed

1 file changed

+201
-1
lines changed

tests/test_mcp_cli_all_host_specific_args.py

Lines changed: 201 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from hatch.mcp_host_config import MCPHostType
1616
from hatch.mcp_host_config.models import (
1717
MCPServerConfigGemini, MCPServerConfigCursor, MCPServerConfigVSCode,
18-
MCPServerConfigClaude
18+
MCPServerConfigClaude, MCPServerConfigCodex
1919
)
2020

2121

@@ -298,6 +298,206 @@ def test_exclude_tools_passed_to_gemini(self, mock_manager_class):
298298
self.assertEqual(server_config.excludeTools, ['dangerous_tool'])
299299

300300

301+
class TestAllCodexArguments(unittest.TestCase):
302+
"""Test ALL Codex-specific CLI arguments."""
303+
304+
@patch('hatch.cli_hatch.MCPHostConfigurationManager')
305+
@patch('sys.stdout', new_callable=StringIO)
306+
def test_all_codex_arguments_accepted(self, mock_stdout, mock_manager_class):
307+
"""Test that all Codex arguments are accepted and passed to model."""
308+
mock_manager = MagicMock()
309+
mock_manager_class.return_value = mock_manager
310+
311+
mock_result = MagicMock()
312+
mock_result.success = True
313+
mock_result.backup_path = None
314+
mock_manager.configure_server.return_value = mock_result
315+
316+
result = handle_mcp_configure(
317+
host='codex',
318+
server_name='test-server',
319+
command='npx',
320+
args=['-y', '@upstash/context7-mcp'],
321+
env_vars=['PATH', 'HOME'],
322+
cwd='/workspace',
323+
startup_timeout=15,
324+
tool_timeout=120,
325+
enabled=True,
326+
include_tools=['read', 'write'],
327+
exclude_tools=['delete'],
328+
bearer_token_env_var='FIGMA_OAUTH_TOKEN',
329+
header=['X-Custom=value'],
330+
env_header=['X-API-Key=API_KEY_VAR'],
331+
auto_approve=True
332+
)
333+
334+
# Verify success
335+
self.assertEqual(result, 0)
336+
337+
# Verify configure_server was called
338+
mock_manager.configure_server.assert_called_once()
339+
340+
# Verify server_config is MCPServerConfigCodex
341+
call_args = mock_manager.configure_server.call_args
342+
server_config = call_args.kwargs['server_config']
343+
self.assertIsInstance(server_config, MCPServerConfigCodex)
344+
345+
# Verify Codex-specific fields
346+
self.assertEqual(server_config.env_vars, ['PATH', 'HOME'])
347+
self.assertEqual(server_config.cwd, '/workspace')
348+
self.assertEqual(server_config.startup_timeout_sec, 15)
349+
self.assertEqual(server_config.tool_timeout_sec, 120)
350+
self.assertTrue(server_config.enabled)
351+
self.assertEqual(server_config.enabled_tools, ['read', 'write'])
352+
self.assertEqual(server_config.disabled_tools, ['delete'])
353+
self.assertEqual(server_config.bearer_token_env_var, 'FIGMA_OAUTH_TOKEN')
354+
self.assertEqual(server_config.http_headers, {'X-Custom': 'value'})
355+
self.assertEqual(server_config.env_http_headers, {'X-API-Key': 'API_KEY_VAR'})
356+
357+
@patch('hatch.cli_hatch.MCPHostConfigurationManager')
358+
@patch('sys.stdout', new_callable=StringIO)
359+
def test_codex_env_vars_list(self, mock_stdout, mock_manager_class):
360+
"""Test that env_vars accepts multiple values as a list."""
361+
mock_manager = MagicMock()
362+
mock_manager_class.return_value = mock_manager
363+
364+
mock_result = MagicMock()
365+
mock_result.success = True
366+
mock_result.backup_path = None
367+
mock_manager.configure_server.return_value = mock_result
368+
369+
result = handle_mcp_configure(
370+
host='codex',
371+
server_name='test-server',
372+
command='npx',
373+
args=['-y', 'package'],
374+
env_vars=['PATH', 'HOME', 'USER'],
375+
auto_approve=True
376+
)
377+
378+
self.assertEqual(result, 0)
379+
call_args = mock_manager.configure_server.call_args
380+
server_config = call_args.kwargs['server_config']
381+
self.assertEqual(server_config.env_vars, ['PATH', 'HOME', 'USER'])
382+
383+
@patch('hatch.cli_hatch.MCPHostConfigurationManager')
384+
@patch('sys.stdout', new_callable=StringIO)
385+
def test_codex_env_header_parsing(self, mock_stdout, mock_manager_class):
386+
"""Test that env_header parses KEY=ENV_VAR format correctly."""
387+
mock_manager = MagicMock()
388+
mock_manager_class.return_value = mock_manager
389+
390+
mock_result = MagicMock()
391+
mock_result.success = True
392+
mock_result.backup_path = None
393+
mock_manager.configure_server.return_value = mock_result
394+
395+
result = handle_mcp_configure(
396+
host='codex',
397+
server_name='test-server',
398+
command='npx',
399+
args=['-y', 'package'],
400+
env_header=['X-API-Key=API_KEY', 'Authorization=AUTH_TOKEN'],
401+
auto_approve=True
402+
)
403+
404+
self.assertEqual(result, 0)
405+
call_args = mock_manager.configure_server.call_args
406+
server_config = call_args.kwargs['server_config']
407+
self.assertEqual(server_config.env_http_headers, {
408+
'X-API-Key': 'API_KEY',
409+
'Authorization': 'AUTH_TOKEN'
410+
})
411+
412+
@patch('hatch.cli_hatch.MCPHostConfigurationManager')
413+
@patch('sys.stdout', new_callable=StringIO)
414+
def test_codex_timeout_fields(self, mock_stdout, mock_manager_class):
415+
"""Test that timeout fields are passed as integers."""
416+
mock_manager = MagicMock()
417+
mock_manager_class.return_value = mock_manager
418+
419+
mock_result = MagicMock()
420+
mock_result.success = True
421+
mock_result.backup_path = None
422+
mock_manager.configure_server.return_value = mock_result
423+
424+
result = handle_mcp_configure(
425+
host='codex',
426+
server_name='test-server',
427+
command='npx',
428+
args=['-y', 'package'],
429+
startup_timeout=30,
430+
tool_timeout=180,
431+
auto_approve=True
432+
)
433+
434+
self.assertEqual(result, 0)
435+
call_args = mock_manager.configure_server.call_args
436+
server_config = call_args.kwargs['server_config']
437+
self.assertEqual(server_config.startup_timeout_sec, 30)
438+
self.assertEqual(server_config.tool_timeout_sec, 180)
439+
440+
@patch('hatch.cli_hatch.MCPHostConfigurationManager')
441+
@patch('sys.stdout', new_callable=StringIO)
442+
def test_codex_enabled_flag(self, mock_stdout, mock_manager_class):
443+
"""Test that enabled flag works as boolean."""
444+
mock_manager = MagicMock()
445+
mock_manager_class.return_value = mock_manager
446+
447+
mock_result = MagicMock()
448+
mock_result.success = True
449+
mock_result.backup_path = None
450+
mock_manager.configure_server.return_value = mock_result
451+
452+
result = handle_mcp_configure(
453+
host='codex',
454+
server_name='test-server',
455+
command='npx',
456+
args=['-y', 'package'],
457+
enabled=True,
458+
auto_approve=True
459+
)
460+
461+
self.assertEqual(result, 0)
462+
call_args = mock_manager.configure_server.call_args
463+
server_config = call_args.kwargs['server_config']
464+
self.assertTrue(server_config.enabled)
465+
466+
@patch('hatch.cli_hatch.MCPHostConfigurationManager')
467+
@patch('sys.stdout', new_callable=StringIO)
468+
def test_codex_reuses_shared_arguments(self, mock_stdout, mock_manager_class):
469+
"""Test that Codex reuses shared arguments (cwd, include-tools, exclude-tools, header)."""
470+
mock_manager = MagicMock()
471+
mock_manager_class.return_value = mock_manager
472+
473+
mock_result = MagicMock()
474+
mock_result.success = True
475+
mock_result.backup_path = None
476+
mock_manager.configure_server.return_value = mock_result
477+
478+
result = handle_mcp_configure(
479+
host='codex',
480+
server_name='test-server',
481+
command='npx',
482+
args=['-y', 'package'],
483+
cwd='/workspace',
484+
include_tools=['tool1', 'tool2'],
485+
exclude_tools=['tool3'],
486+
header=['X-Custom=value'],
487+
auto_approve=True
488+
)
489+
490+
self.assertEqual(result, 0)
491+
call_args = mock_manager.configure_server.call_args
492+
server_config = call_args.kwargs['server_config']
493+
494+
# Verify shared arguments work for Codex
495+
self.assertEqual(server_config.cwd, '/workspace')
496+
self.assertEqual(server_config.enabled_tools, ['tool1', 'tool2'])
497+
self.assertEqual(server_config.disabled_tools, ['tool3'])
498+
self.assertEqual(server_config.http_headers, {'X-Custom': 'value'})
499+
500+
301501
if __name__ == '__main__':
302502
unittest.main()
303503

0 commit comments

Comments
 (0)