# Django Integration Tests - Storm Logger

## Quick Overview for Gemini

This directory contains Django-specific integration tests for Storm Logger. It includes a minimal Django application setup to test logging integration, middleware, database handlers, and Django-specific features.

## Test Structure

```
django_hooks/
├── settings.py               # Django test settings
├── urls.py                   # URL configuration
├── test_django_integration.py # Main Django tests
└── test_app/                 # Minimal Django app
    ├── apps.py              # App configuration
    ├── models.py            # Test models
    ├── views.py             # Test views
    └── urls.py              # App URLs
```

## Django Test Environment

### Test Settings (`settings.py`)
```python
# Minimal Django configuration for testing
INSTALLED_APPS = [
    'django.contrib.contenttypes',
    'django.contrib.auth',
    'tests.django_hooks.test_app',
]

# Storm Logger configuration
STORM_LOGGER_CONFIG = StormLoggerConfig.generate_django_config()
LOGGING = STORM_LOGGER_CONFIG

# Database for testing
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': ':memory:',
    }
}
```

### Test Application Structure
The `test_app` provides a minimal Django application with:
- Models for testing database logging
- Views for testing request/response logging
- URLs for routing test requests
- App configuration for Django integration

## Key Test Scenarios

### 1. Django Configuration Integration
```python
def test_django_settings_integration():
    """Test that Storm Logger integrates with Django settings."""
    from django.conf import settings
    
    # Verify LOGGING configuration
    assert 'storm_logger' in settings.LOGGING['loggers']
    assert settings.LOGGING['version'] == 1
    
    # Verify handlers are configured
    assert 'storm_console' in settings.LOGGING['handlers']
    assert 'storm_file' in settings.LOGGING['handlers']
```

### 2. Request/Response Logging
```python
@pytest.mark.django_db
def test_request_logging(client):
    """Test Django request/response cycle logging."""
    # Make a test request
    response = client.get('/test/')
    
    # Verify request was logged
    assert response.status_code == 200
    
    # Check logs contain request information
    logs = get_recent_logs()
    assert any('GET /test/' in log for log in logs)
    assert any('status=200' in log for log in logs)
```

### 3. Database Log Handler
```python
@pytest.mark.django_db
def test_database_log_handler():
    """Test logging to Django database."""
    from storm_logger.integrations.django import DatabaseLogHandler
    from tests.django_hooks.test_app.models import LogEntry
    
    # Configure database handler
    logger = get_storm_logger('django_test')
    db_handler = DatabaseLogHandler(model='test_app.LogEntry')
    logger.addHandler(db_handler)
    
    # Log a message
    logger.warning("Database test", extra={'user_id': 123})
    
    # Verify database entry
    log_entry = LogEntry.objects.latest('timestamp')
    assert log_entry.level == 'WARNING'
    assert log_entry.message == 'Database test'
    assert log_entry.extra_data['user_id'] == 123
```

### 4. Django Middleware Integration
```python
def test_storm_logger_middleware(client):
    """Test Storm Logger middleware."""
    # Middleware should add logging context
    response = client.get('/test/', HTTP_USER_AGENT='TestBot/1.0')
    
    # Verify context was captured
    logs = get_recent_logs()
    context_log = next(log for log in logs if 'request_id' in log)
    
    assert 'user_agent=TestBot/1.0' in context_log
    assert 'method=GET' in context_log
    assert 'path=/test/' in context_log
```

### 5. Django Admin Integration
```python
@pytest.mark.django_db
def test_admin_action_logging(admin_client):
    """Test logging of Django admin actions."""
    # Create test object
    from tests.django_hooks.test_app.models import TestModel
    obj = TestModel.objects.create(name="Test")
    
    # Perform admin action
    response = admin_client.post(
        f'/admin/test_app/testmodel/{obj.id}/delete/',
        {'post': 'yes'}
    )
    
    # Verify admin action was logged
    logs = get_recent_logs()
    assert any('admin_action=delete' in log for log in logs)
    assert any(f'object_id={obj.id}' in log for log in logs)
```

## Django-Specific Features

### 1. Signal Handlers
```python
def test_model_signal_logging():
    """Test model save/delete signal logging."""
    from tests.django_hooks.test_app.models import TestModel
    
    # Create model instance
    instance = TestModel(name="Signal Test")
    instance.save()
    
    # Verify pre_save and post_save logged
    logs = get_recent_logs()
    assert any('signal=pre_save' in log for log in logs)
    assert any('signal=post_save' in log for log in logs)
    
    # Delete instance
    instance.delete()
    
    # Verify delete signals logged
    assert any('signal=pre_delete' in log for log in logs)
    assert any('signal=post_delete' in log for log in logs)
```

### 2. Management Command Logging
```python
def test_management_command_logging():
    """Test Django management command logging."""
    from django.core.management import call_command
    from io import StringIO
    
    out = StringIO()
    
    # Run a management command
    call_command('storm_logger_test', stdout=out)
    
    # Verify command execution logged
    logs = get_recent_logs()
    assert any('management_command=storm_logger_test' in log for log in logs)
    assert any('command_status=success' in log for log in logs)
```

### 3. Template Rendering Logging
```python
def test_template_rendering_logging(client):
    """Test template rendering is logged."""
    # Request a view that renders a template
    response = client.get('/template-test/')
    
    # Verify template rendering logged
    logs = get_recent_logs()
    assert any('template=test_template.html' in log for log in logs)
    assert any('context_vars=' in log for log in logs)
```

## Test Utilities

### 1. Django Test Client Extensions
```python
class StormLoggerTestClient(Client):
    """Extended test client with logging assertions."""
    
    def assertLogged(self, message, level=None):
        """Assert a message was logged."""
        logs = get_recent_logs()
        assert any(message in log for log in logs)
        
        if level:
            level_logs = [log for log in logs if f'level={level}' in log]
            assert any(message in log for log in level_logs)
```

### 2. Database Log Queries
```python
def get_logs_for_request(request_id):
    """Get all logs for a specific request."""
    from tests.django_hooks.test_app.models import LogEntry
    
    return LogEntry.objects.filter(
        extra_data__request_id=request_id
    ).order_by('timestamp')
```

### 3. Fixture Helpers
```python
@pytest.fixture
def logged_user(db):
    """Create a user with logged actions."""
    from django.contrib.auth.models import User
    
    user = User.objects.create_user('testuser', 'test@example.com')
    
    # Log user creation
    logger = get_storm_logger('test')
    logger.info("User created", user_id=user.id, username=user.username)
    
    return user
```

## Performance Considerations

### 1. Database Handler Performance
```python
def test_database_handler_bulk_performance():
    """Test database handler with bulk operations."""
    logger = get_storm_logger('bulk_test')
    
    start = time.time()
    
    # Log many messages
    for i in range(1000):
        logger.info(f"Bulk message {i}")
    
    duration = time.time() - start
    
    # Should handle 1000 messages efficiently
    assert duration < 5.0  # Less than 5 seconds
    
    # Verify all messages were saved
    from tests.django_hooks.test_app.models import LogEntry
    assert LogEntry.objects.count() == 1000
```

### 2. Middleware Overhead
```python
def test_middleware_performance_impact(client, benchmark):
    """Test middleware doesn't significantly impact response time."""
    
    def make_request():
        response = client.get('/test/')
        assert response.status_code == 200
    
    # Benchmark with middleware
    with_middleware = benchmark(make_request)
    
    # Temporarily disable middleware and benchmark
    without_middleware = benchmark_without_middleware(make_request)
    
    # Overhead should be minimal (< 10%)
    overhead = (with_middleware - without_middleware) / without_middleware
    assert overhead < 0.10
```

## Integration Test Patterns

### 1. Full Request Cycle
```python
def test_complete_request_cycle():
    """Test complete Django request/response cycle with logging."""
    client = Client()
    
    # Authenticate
    client.login(username='testuser', password='testpass')
    
    # Make request
    response = client.post('/api/data/', {
        'name': 'Test Data',
        'value': 42
    })
    
    # Verify response
    assert response.status_code == 201
    data = response.json()
    
    # Verify complete logging trail
    logs = get_logs_for_request(response['X-Request-ID'])
    
    # Should have logs for:
    assert any('authentication' in log.message for log in logs)
    assert any('view_entered' in log.message for log in logs)
    assert any('model_created' in log.message for log in logs)
    assert any('response_sent' in log.message for log in logs)
```

### 2. Error Handling
```python
def test_exception_logging(client):
    """Test exception handling and logging."""
    # Trigger an error
    response = client.get('/error/')
    
    # Should return 500
    assert response.status_code == 500
    
    # Verify exception was logged
    logs = get_recent_logs()
    error_logs = [log for log in logs if 'level=ERROR' in log]
    
    assert len(error_logs) > 0
    assert any('TestException' in log for log in error_logs)
    assert any('traceback' in log for log in error_logs)
```

## Running Django Tests

```bash
# Run all Django integration tests
pytest tests/django_hooks/ -v

# Run with Django database
pytest tests/django_hooks/ --create-db

# Run specific test
pytest tests/django_hooks/test_django_integration.py::test_request_logging

# Run with Django debug
DJANGO_DEBUG=1 pytest tests/django_hooks/

# Generate coverage for Django code
pytest tests/django_hooks/ --cov=storm_logger.integrations.django
```

## Best Practices

### 1. Test Isolation
- Use transactions for database tests
- Clear caches between tests
- Reset global state

### 2. Realistic Testing
- Use actual Django models
- Test with real middleware stack
- Include authentication/permissions

### 3. Django Versions
- Test with multiple Django versions
- Handle deprecation warnings
- Maintain compatibility

## Troubleshooting

### Common Issues
1. **Import Errors**: Ensure DJANGO_SETTINGS_MODULE is set
2. **Database Errors**: Use `@pytest.mark.django_db`
3. **Settings Conflicts**: Use isolated test settings
4. **Migration Issues**: Use in-memory database

### Debug Commands
```bash
# Check Django setup
python -c "import django; django.setup(); print('Django OK')"

# Run Django shell with test settings
DJANGO_SETTINGS_MODULE=tests.django_hooks.settings python manage.py shell

# Check test database
python manage.py dbshell
```

## Next Steps

- Add more Django feature tests
- Test with Django REST framework
- Add Celery integration tests
- Test with different Django versions
- Add performance benchmarks for Django