191 lines
7.2 KiB
Python
191 lines
7.2 KiB
Python
"""
|
|||
|
|
Integration tests for Claude API configuration system
|
||
|
|
Tests Skills with different Claude API configurations, environment variables, and backward compatibility
|
||
|
|
"""
|
||
|
|
|
||
|
|
import os
|
||
|
|
import pytest
|
||
|
|
import tempfile
|
||
|
|
import yaml
|
||
|
|
from pathlib import Path
|
||
|
|
from unittest.mock import Mock, patch, AsyncMock
|
||
|
|
from typing import Dict, Any
|
||
|
|
|
||
|
|
# Import the modules we're testing
|
||
|
|
import sys
|
||
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||
|
|
|
||
|
|
from config_validation import ClaudeAPIConfig
|
||
|
|
from configuration_loader import ConfigurationLoader
|
||
|
|
from configuration_migrator import ConfigurationMigrator
|
||
|
|
|
||
|
|
|
||
|
|
class TestEnvironmentVariableIntegration:
|
||
|
|
"""Test environment variable scenarios in configuration"""
|
||
|
|
|
||
|
|
def setup_method(self):
|
||
|
|
"""Set up test fixtures"""
|
||
|
|
self.temp_dir = Path(tempfile.mkdtemp())
|
||
|
|
self.loader = ConfigurationLoader()
|
||
|
|
self.migrator = ConfigurationMigrator()
|
||
|
|
|
||
|
|
def teardown_method(self):
|
||
|
|
"""Clean up test fixtures"""
|
||
|
|
import shutil
|
||
|
|
shutil.rmtree(self.temp_dir)
|
||
|
|
|
||
|
|
# Clean up any test environment variables
|
||
|
|
test_vars = ['TEST_CLAUDE_API_KEY', 'TEST_CLAUDE_API_URL', 'TEST_CLAUDE_MODEL']
|
||
|
|
for var in test_vars:
|
||
|
|
if var in os.environ:
|
||
|
|
del os.environ[var]
|
||
|
|
|
||
|
|
def create_test_config_file(self, config_data: Dict[str, Any]) -> Path:
|
||
|
|
"""Create a test configuration file"""
|
||
|
|
config_file = self.temp_dir / 'test_config.yaml'
|
||
|
|
with config_file.open('w') as f:
|
||
|
|
yaml.dump(config_data, f)
|
||
|
|
return config_file
|
||
|
|
|
||
|
|
def test_environment_variable_expansion(self):
|
||
|
|
"""Test environment variable expansion"""
|
||
|
|
# Set up environment variables
|
||
|
|
os.environ['TEST_CLAUDE_API_KEY'] = 'sk-ant-test-key-12345678901234567890123456789012345678901234567890'
|
||
|
|
os.environ['TEST_CLAUDE_API_URL'] = 'https://custom-api.example.com'
|
||
|
|
|
||
|
|
config_data = {
|
||
|
|
'claude': {
|
||
|
|
'api_key': '${TEST_CLAUDE_API_KEY}',
|
||
|
|
'api_url': '${TEST_CLAUDE_API_URL}',
|
||
|
|
'model': 'claude-3-5-sonnet-20241022'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
expanded = self.loader.expand_environment_variables(config_data)
|
||
|
|
|
||
|
|
assert expanded['claude']['api_key'] == 'sk-ant-test-key-12345678901234567890123456789012345678901234567890'
|
||
|
|
assert expanded['claude']['api_url'] == 'https://custom-api.example.com'
|
||
|
|
assert expanded['claude']['model'] == 'claude-3-5-sonnet-20241022'
|
||
|
|
|
||
|
|
def test_environment_variable_defaults(self):
|
||
|
|
"""Test environment variable expansion with defaults"""
|
||
|
|
config_data = {
|
||
|
|
'claude': {
|
||
|
|
'api_key': 'sk-ant-test-key-12345678901234567890123456789012345678901234567890',
|
||
|
|
'api_url': '${CLAUDE_API_URL:-https://api.anthropic.com}',
|
||
|
|
'model': '${CLAUDE_MODEL:-claude-3-5-sonnet-20241022}'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
expanded = self.loader.expand_environment_variables(config_data)
|
||
|
|
|
||
|
|
# Should use defaults since env vars are not set
|
||
|
|
assert expanded['claude']['api_url'] == 'https://api.anthropic.com'
|
||
|
|
assert expanded['claude']['model'] == 'claude-3-5-sonnet-20241022'
|
||
|
|
|
||
|
|
|
||
|
|
class TestBackwardCompatibilityIntegration:
|
||
|
|
"""Test backward compatibility with existing setups"""
|
||
|
|
|
||
|
|
def setup_method(self):
|
||
|
|
"""Set up test fixtures"""
|
||
|
|
self.migrator = ConfigurationMigrator()
|
||
|
|
|
||
|
|
def test_legacy_model_migration(self):
|
||
|
|
"""Test migration of legacy model names"""
|
||
|
|
legacy_config = {
|
||
|
|
'claude': {
|
||
|
|
'api_key': 'sk-ant-test-key-12345678901234567890123456789012345678901234567890',
|
||
|
|
'model': 'claude-3-sonnet' # Legacy model name
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
migrated = self.migrator.migrate_claude_config(legacy_config)
|
||
|
|
|
||
|
|
# Should migrate to new model name
|
||
|
|
assert migrated['claude']['model'] == 'claude-3-sonnet-20240229'
|
||
|
|
# Should add default API URL
|
||
|
|
assert migrated['claude']['api_url'] == 'https://api.anthropic.com'
|
||
|
|
|
||
|
|
def test_migration_needed_detection(self):
|
||
|
|
"""Test detection of configurations that need migration"""
|
||
|
|
# Config that needs migration
|
||
|
|
legacy_config = {
|
||
|
|
'claude': {
|
||
|
|
'api_key': 'sk-ant-test-key-12345678901234567890123456789012345678901234567890',
|
||
|
|
'model': 'claude-3-opus' # Legacy model name
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
assert self.migrator.check_migration_needed(legacy_config) is True
|
||
|
|
|
||
|
|
# Config that doesn't need migration
|
||
|
|
modern_config = {
|
||
|
|
'claude': {
|
||
|
|
'api_key': 'sk-ant-test-key-12345678901234567890123456789012345678901234567890',
|
||
|
|
'api_url': 'https://api.anthropic.com',
|
||
|
|
'model': 'claude-3-5-sonnet-20241022',
|
||
|
|
'max_tokens': 4096,
|
||
|
|
'temperature': 0.7
|
||
|
|
},
|
||
|
|
'journal': {
|
||
|
|
'daily_notes_folder': 'Daily',
|
||
|
|
'date_format': 'YYYY-MM-DD',
|
||
|
|
'file_extension': '.md'
|
||
|
|
},
|
||
|
|
'output': {
|
||
|
|
'experiences_folder': 'Knowledge/Experiences',
|
||
|
|
'lessons_folder': 'Knowledge/Lessons',
|
||
|
|
'tasks_folder': 'Tasks/Daily',
|
||
|
|
'problems_folder': 'Knowledge/Problems',
|
||
|
|
'achievements_folder': 'Knowledge/Achievements',
|
||
|
|
'improvements_folder': 'Knowledge/Improvements'
|
||
|
|
},
|
||
|
|
'analysis': {
|
||
|
|
'categories': [],
|
||
|
|
'extraction_rules': {}
|
||
|
|
},
|
||
|
|
'logging': {
|
||
|
|
'level': 'INFO',
|
||
|
|
'file': 'logs/journal_organizer.log'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
assert self.migrator.check_migration_needed(modern_config) is False
|
||
|
|
|
||
|
|
|
||
|
|
class TestConfigurationValidation:
|
||
|
|
"""Test configuration validation scenarios"""
|
||
|
|
|
||
|
|
def test_claude_api_config_validation(self):
|
||
|
|
"""Test ClaudeAPIConfig validation"""
|
||
|
|
# Valid configuration
|
||
|
|
config = ClaudeAPIConfig(
|
||
|
|
api_key='sk-ant-test-key-12345678901234567890123456789012345678901234567890',
|
||
|
|
api_url='https://custom-api.example.com',
|
||
|
|
model='claude-3-5-sonnet-20241022'
|
||
|
|
)
|
||
|
|
|
||
|
|
assert config.api_key.startswith('sk-ant-')
|
||
|
|
assert config.api_url == 'https://custom-api.example.com'
|
||
|
|
assert config.model == 'claude-3-5-sonnet-20241022'
|
||
|
|
|
||
|
|
def test_invalid_configuration_handling(self):
|
||
|
|
"""Test handling of invalid configurations"""
|
||
|
|
# Invalid API key format
|
||
|
|
with pytest.raises(ValueError, match="Claude API key should start with"):
|
||
|
|
ClaudeAPIConfig(api_key='invalid-key')
|
||
|
|
|
||
|
|
# Invalid URL format
|
||
|
|
with pytest.raises(ValueError, match="Invalid URL format"):
|
||
|
|
ClaudeAPIConfig(
|
||
|
|
api_key='sk-ant-test-key-12345678901234567890123456789012345678901234567890',
|
||
|
|
api_url='not-a-url'
|
||
|
|
)
|
||
|
|
|
||
|
|
# Invalid model name
|
||
|
|
with pytest.raises(ValueError, match="Invalid model name"):
|
||
|
|
ClaudeAPIConfig(
|
||
|
|
api_key='sk-ant-test-key-12345678901234567890123456789012345678901234567890',
|
||
|
|
model='invalid-model'
|
||
|
|
)
|