Files
journal_organizer/tests/integration/test_claude_api_integration.py
windyboy f7e54692a9 Initial project setup: Obsidian intelligent journal organizer
- Add core agent architecture with Command + Skill pattern
- Implement Claude API integration for content analysis
- Add Obsidian REST API integration for vault operations
- Create conversational interface (v2.0) with natural language processing
- Add comprehensive configuration management and validation
- Include project documentation and developer guides
- Set up testing framework with unit, integration, and property tests
- Add Kiro specs for Claude API configuration and code quality improvements
- Configure project steering files for development guidelines
2025-12-31 17:55:10 +08:00

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'
)