Spaces:
Running
Running
| import json | |
| import pytest | |
| from unittest.mock import MagicMock, patch | |
| from fastapi.testclient import TestClient | |
| from fastapi import FastAPI | |
| import sys | |
| import os | |
| sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) | |
| from backend.data_sources.api import router, get_redis_client, get_tenant_config | |
| from backend.core.auth import AuthUser, get_current_user | |
| app = FastAPI() | |
| app.include_router(router) | |
| def mock_get_current_user(): | |
| return AuthUser({ | |
| "id": "test_user", | |
| "user_metadata": {"tenant_id": "test_tenant", "role": "user"} | |
| }) | |
| app.dependency_overrides[get_current_user] = mock_get_current_user | |
| client = TestClient(app) | |
| class TestPatchAndDeleteEndpoints: | |
| def test_patch_tenant_source(self, mock_redis): | |
| mock_redis_instance = MagicMock() | |
| mock_redis.return_value = mock_redis_instance | |
| # Existing config | |
| existing_config = [ | |
| { | |
| "source_name": "old_db", | |
| "source_type": "ibis", | |
| "config": {"uri": "postgres://user:pass@localhost:5432/db1", "other": "val"} | |
| } | |
| ] | |
| mock_redis_instance.get.return_value = json.dumps(existing_config) | |
| # Override the dependency for the duration of the request | |
| app.dependency_overrides[get_redis_client] = lambda: mock_redis_instance | |
| patch_request = { | |
| "new_source_name": "new_db", | |
| "config_updates": {"uri": "postgres://user:newpass@localhost:5432/db1"} | |
| } | |
| response = client.patch("/api/v1/data-sources/my-tenant/sources/old_db?validate_connection=false", json=patch_request) | |
| # Clean up | |
| app.dependency_overrides.pop(get_redis_client, None) | |
| assert response.status_code == 200 | |
| # Check that set was called with updated config | |
| mock_redis_instance.set.assert_called_once() | |
| args, _ = mock_redis_instance.set.call_args | |
| key, value = args | |
| assert key == "tenant:test_tenant:config" | |
| updated_sources = json.loads(value) | |
| assert len(updated_sources) == 1 | |
| assert updated_sources[0]["source_name"] == "new_db" | |
| assert updated_sources[0]["config"]["uri"] == "postgres://user:newpass@localhost:5432/db1" | |
| assert updated_sources[0]["config"]["other"] == "val" # Ensure config was merged, not replaced | |
| def test_delete_tenant_source_cascades(self, mock_redis): | |
| mock_redis_instance = MagicMock() | |
| mock_redis.return_value = mock_redis_instance | |
| existing_config = [{"source_name": "db_to_delete", "config": {}}] | |
| mock_redis_instance.get.return_value = json.dumps(existing_config) | |
| app.dependency_overrides[get_redis_client] = lambda: mock_redis_instance | |
| response = client.delete("/api/v1/data-sources/my-tenant/sources/db_to_delete") | |
| app.dependency_overrides.pop(get_redis_client, None) | |
| assert response.status_code == 200 | |
| # Redis delete should be called for caches | |
| delete_calls = mock_redis_instance.delete.call_args_list | |
| assert any(call[0][0] == "schema:test_tenant:db_to_delete" for call in delete_calls) | |
| assert any(call[0][0] == "instructions:test_tenant:db_to_delete" for call in delete_calls) | |