mirror of
https://github.com/mwisnowski/mtg_python_deckbuilder.git
synced 2025-12-17 08:00:13 +01:00
feat(cli): add type indicators, ideal count args, and theme name support
Enhanced CLI with type-safe help text, 8 ideal count flags (--land-count, etc), and theme selection by name (--primary-tag)
This commit is contained in:
parent
cfcc01db85
commit
abea242c16
6 changed files with 588 additions and 79 deletions
137
code/tests/test_cli_include_exclude.py
Normal file
137
code/tests/test_cli_include_exclude.py
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
"""
|
||||
Test CLI include/exclude functionality (M4: CLI Parity).
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import subprocess
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class TestCLIIncludeExclude:
|
||||
"""Test CLI include/exclude argument parsing and functionality."""
|
||||
|
||||
def test_cli_argument_parsing(self):
|
||||
"""Test that CLI arguments are properly parsed."""
|
||||
# Test help output includes new arguments
|
||||
result = subprocess.run(
|
||||
['python', 'code/headless_runner.py', '--help'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=Path(__file__).parent.parent.parent
|
||||
)
|
||||
|
||||
assert result.returncode == 0
|
||||
help_text = result.stdout
|
||||
assert '--include-cards' in help_text
|
||||
assert '--exclude-cards' in help_text
|
||||
assert '--enforcement-mode' in help_text
|
||||
assert '--allow-illegal' in help_text
|
||||
assert '--fuzzy-matching' in help_text
|
||||
assert 'semicolons' in help_text # Check for comma warning
|
||||
|
||||
def test_cli_dry_run_with_include_exclude(self):
|
||||
"""Test dry run output includes include/exclude configuration."""
|
||||
result = subprocess.run([
|
||||
'python', 'code/headless_runner.py',
|
||||
'--commander', 'Krenko, Mob Boss',
|
||||
'--include-cards', 'Sol Ring;Lightning Bolt',
|
||||
'--exclude-cards', 'Chaos Orb',
|
||||
'--enforcement-mode', 'strict',
|
||||
'--dry-run'
|
||||
], capture_output=True, text=True, cwd=Path(__file__).parent.parent.parent)
|
||||
|
||||
assert result.returncode == 0
|
||||
|
||||
# Parse the JSON output
|
||||
config = json.loads(result.stdout)
|
||||
|
||||
assert config['command_name'] == 'Krenko, Mob Boss'
|
||||
assert config['include_cards'] == ['Sol Ring', 'Lightning Bolt']
|
||||
assert config['exclude_cards'] == ['Chaos Orb']
|
||||
assert config['enforcement_mode'] == 'strict'
|
||||
|
||||
def test_cli_semicolon_parsing(self):
|
||||
"""Test semicolon separation for card names with commas."""
|
||||
result = subprocess.run([
|
||||
'python', 'code/headless_runner.py',
|
||||
'--include-cards', 'Krenko, Mob Boss;Jace, the Mind Sculptor',
|
||||
'--exclude-cards', 'Teferi, Hero of Dominaria',
|
||||
'--dry-run'
|
||||
], capture_output=True, text=True, cwd=Path(__file__).parent.parent.parent)
|
||||
|
||||
assert result.returncode == 0
|
||||
|
||||
config = json.loads(result.stdout)
|
||||
assert config['include_cards'] == ['Krenko, Mob Boss', 'Jace, the Mind Sculptor']
|
||||
assert config['exclude_cards'] == ['Teferi, Hero of Dominaria']
|
||||
|
||||
def test_cli_comma_parsing_simple_names(self):
|
||||
"""Test comma separation for simple card names without commas."""
|
||||
result = subprocess.run([
|
||||
'python', 'code/headless_runner.py',
|
||||
'--include-cards', 'Sol Ring,Lightning Bolt,Counterspell',
|
||||
'--exclude-cards', 'Island,Mountain',
|
||||
'--dry-run'
|
||||
], capture_output=True, text=True, cwd=Path(__file__).parent.parent.parent)
|
||||
|
||||
assert result.returncode == 0
|
||||
|
||||
config = json.loads(result.stdout)
|
||||
assert config['include_cards'] == ['Sol Ring', 'Lightning Bolt', 'Counterspell']
|
||||
assert config['exclude_cards'] == ['Island', 'Mountain']
|
||||
|
||||
def test_cli_json_priority(self):
|
||||
"""Test that CLI arguments override JSON config values."""
|
||||
# Create a temporary JSON config
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
|
||||
json.dump({
|
||||
'commander': 'Atraxa, Praetors\' Voice',
|
||||
'include_cards': ['Doubling Season'],
|
||||
'exclude_cards': ['Winter Orb'],
|
||||
'enforcement_mode': 'warn'
|
||||
}, f, indent=2)
|
||||
temp_config = f.name
|
||||
|
||||
try:
|
||||
result = subprocess.run([
|
||||
'python', 'code/headless_runner.py',
|
||||
'--config', temp_config,
|
||||
'--include-cards', 'Sol Ring', # Override JSON
|
||||
'--enforcement-mode', 'strict', # Override JSON
|
||||
'--dry-run'
|
||||
], capture_output=True, text=True, cwd=Path(__file__).parent.parent.parent)
|
||||
|
||||
assert result.returncode == 0
|
||||
|
||||
config = json.loads(result.stdout)
|
||||
# CLI should override JSON
|
||||
assert config['include_cards'] == ['Sol Ring'] # CLI override
|
||||
assert config['exclude_cards'] == ['Winter Orb'] # From JSON (no CLI override)
|
||||
assert config['enforcement_mode'] == 'strict' # CLI override
|
||||
|
||||
finally:
|
||||
os.unlink(temp_config)
|
||||
|
||||
def test_cli_empty_values(self):
|
||||
"""Test handling of empty/missing include/exclude values."""
|
||||
result = subprocess.run([
|
||||
'python', 'code/headless_runner.py',
|
||||
'--commander', 'Krenko, Mob Boss',
|
||||
'--dry-run'
|
||||
], capture_output=True, text=True, cwd=Path(__file__).parent.parent.parent)
|
||||
|
||||
assert result.returncode == 0
|
||||
|
||||
config = json.loads(result.stdout)
|
||||
assert config['include_cards'] == []
|
||||
assert config['exclude_cards'] == []
|
||||
assert config['enforcement_mode'] == 'warn' # Default
|
||||
assert config['allow_illegal'] is False # Default
|
||||
assert config['fuzzy_matching'] is True # Default
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pytest.main([__file__])
|
||||
Loading…
Add table
Add a link
Reference in a new issue