"""Integration tests for configuration API endpoints.""" import tempfile from pathlib import Path from unittest.mock import patch import pytest from fastapi.testclient import TestClient from src.server.fastapi_app import app from src.server.models.config import AppConfig from src.server.services.config_service import ConfigService @pytest.fixture def temp_config_dir(): """Create temporary directory for test config files.""" with tempfile.TemporaryDirectory() as tmpdir: yield Path(tmpdir) @pytest.fixture def config_service(temp_config_dir): """Create ConfigService instance with temporary paths.""" config_path = temp_config_dir / "config.json" backup_dir = temp_config_dir / "backups" return ConfigService( config_path=config_path, backup_dir=backup_dir, max_backups=3 ) @pytest.fixture def mock_config_service(config_service): """Mock get_config_service to return test instance.""" with patch( "src.server.api.config.get_config_service", return_value=config_service ): yield config_service @pytest.fixture def client(): """Create test client.""" return TestClient(app) def test_get_config_public(client, mock_config_service): """Test getting configuration.""" resp = client.get("/api/config") assert resp.status_code == 200 data = resp.json() assert "name" in data assert "data_dir" in data def test_validate_config(client, mock_config_service): """Test configuration validation.""" cfg = { "name": "Aniworld", "data_dir": "data", "scheduler": {"enabled": True, "interval_minutes": 30}, "logging": {"level": "INFO"}, "backup": {"enabled": False}, "other": {}, } resp = client.post("/api/config/validate", json=cfg) assert resp.status_code == 200 body = resp.json() assert body.get("valid") is True def test_validate_invalid_config(client, mock_config_service): """Test validation of invalid configuration.""" cfg = { "name": "Aniworld", "backup": {"enabled": True, "path": None}, # Invalid } resp = client.post("/api/config/validate", json=cfg) assert resp.status_code == 200 body = resp.json() assert body.get("valid") is False assert len(body.get("errors", [])) > 0 def test_update_config_unauthorized(client): """Test that update requires authentication.""" update = {"scheduler": {"enabled": False}} resp = client.put("/api/config", json=update) assert resp.status_code in (401, 422) def test_list_backups(client, mock_config_service): """Test listing configuration backups.""" # Create a sample config first sample_config = AppConfig(name="TestApp", data_dir="test_data") mock_config_service.save_config(sample_config, create_backup=False) mock_config_service.create_backup(name="test_backup") resp = client.get("/api/config/backups") assert resp.status_code == 200 backups = resp.json() assert isinstance(backups, list) if len(backups) > 0: assert "name" in backups[0] assert "size_bytes" in backups[0] assert "created_at" in backups[0] def test_create_backup(client, mock_config_service): """Test creating a configuration backup.""" # Create a sample config first sample_config = AppConfig(name="TestApp", data_dir="test_data") mock_config_service.save_config(sample_config, create_backup=False) resp = client.post("/api/config/backups") assert resp.status_code == 200 data = resp.json() assert "name" in data assert "message" in data def test_restore_backup(client, mock_config_service): """Test restoring configuration from backup.""" # Create initial config and backup sample_config = AppConfig(name="TestApp", data_dir="test_data") mock_config_service.save_config(sample_config, create_backup=False) mock_config_service.create_backup(name="restore_test") # Modify config sample_config.name = "Modified" mock_config_service.save_config(sample_config, create_backup=False) # Restore from backup resp = client.post("/api/config/backups/restore_test.json/restore") assert resp.status_code == 200 data = resp.json() assert data["name"] == "TestApp" # Original name restored def test_delete_backup(client, mock_config_service): """Test deleting a configuration backup.""" # Create a sample config and backup sample_config = AppConfig(name="TestApp", data_dir="test_data") mock_config_service.save_config(sample_config, create_backup=False) mock_config_service.create_backup(name="delete_test") resp = client.delete("/api/config/backups/delete_test.json") assert resp.status_code == 200 data = resp.json() assert "deleted successfully" in data["message"] def test_config_persistence(client, mock_config_service): """Test end-to-end configuration persistence.""" # Get initial config resp = client.get("/api/config") assert resp.status_code == 200 initial = resp.json() # Validate it can be loaded again resp2 = client.get("/api/config") assert resp2.status_code == 200 assert resp2.json() == initial