Files
Aether/tests/api/test_admin_provider_routes.py

129 lines
4.1 KiB
Python
Raw Normal View History

from __future__ import annotations
from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock
import pytest
from src.api.admin.providers.routes import (
AdminDeleteProviderAdapter,
AdminProviderDeleteTaskStatusAdapter,
)
@pytest.mark.asyncio
async def test_delete_provider_adapter_submits_async_task_and_deactivates_provider(
monkeypatch: pytest.MonkeyPatch,
) -> None:
db = MagicMock()
provider = SimpleNamespace(id="provider-1", name="Provider 1", is_active=True)
db.query.return_value.filter.return_value.first.return_value = provider
submit_task_mock = AsyncMock(return_value="task-1")
invalidate_models_mock = AsyncMock()
invalidate_resolve_mock = AsyncMock()
invalidate_provider_cache_mock = AsyncMock()
monkeypatch.setattr(
"src.api.admin.providers.routes.submit_provider_delete",
submit_task_mock,
)
monkeypatch.setattr(
"src.api.admin.providers.routes.invalidate_models_list_cache",
invalidate_models_mock,
)
monkeypatch.setattr(
"src.api.admin.providers.routes.ModelCacheService.invalidate_all_resolve_cache",
invalidate_resolve_mock,
)
monkeypatch.setattr(
"src.api.admin.providers.routes.ProviderCacheService.invalidate_provider_cache",
invalidate_provider_cache_mock,
)
audit_calls: list[dict[str, object]] = []
context = SimpleNamespace(
db=db,
request=SimpleNamespace(state=SimpleNamespace()),
add_audit_metadata=lambda **kwargs: audit_calls.append(kwargs),
)
adapter = AdminDeleteProviderAdapter(provider_id="provider-1")
result = await adapter.handle(context)
assert result == {
"task_id": "task-1",
"status": "pending",
"message": "删除任务已提交,提供商已进入后台删除队列",
}
submit_task_mock.assert_awaited_once_with("provider-1")
assert provider.is_active is False
db.commit.assert_called_once()
invalidate_models_mock.assert_awaited_once()
invalidate_resolve_mock.assert_awaited_once()
invalidate_provider_cache_mock.assert_awaited_once_with("provider-1")
assert audit_calls[0]["action"] == "delete_provider"
assert audit_calls[1]["task_id"] == "task-1"
assert audit_calls[1]["provider_deactivated"] is True
@pytest.mark.asyncio
async def test_delete_provider_adapter_reuses_task_without_extra_commit(
monkeypatch: pytest.MonkeyPatch,
) -> None:
db = MagicMock()
provider = SimpleNamespace(id="provider-1", name="Provider 1", is_active=False)
db.query.return_value.filter.return_value.first.return_value = provider
submit_task_mock = AsyncMock(return_value="task-1")
monkeypatch.setattr(
"src.api.admin.providers.routes.submit_provider_delete",
submit_task_mock,
)
context = SimpleNamespace(
db=db,
request=SimpleNamespace(state=SimpleNamespace()),
add_audit_metadata=lambda **kwargs: None,
)
adapter = AdminDeleteProviderAdapter(provider_id="provider-1")
result = await adapter.handle(context)
assert result["task_id"] == "task-1"
db.commit.assert_not_called()
@pytest.mark.asyncio
async def test_delete_provider_task_status_adapter_returns_task_payload(
monkeypatch: pytest.MonkeyPatch,
) -> None:
task = SimpleNamespace(
task_id="task-1",
provider_id="provider-1",
status="running",
stage="deleting_keys",
total_keys=100,
deleted_keys=25,
total_endpoints=8,
deleted_endpoints=2,
message="deleted key batch 1/2",
)
monkeypatch.setattr(
"src.api.admin.providers.routes.get_provider_delete_task",
AsyncMock(return_value=task),
)
context = SimpleNamespace(db=MagicMock(), request=SimpleNamespace(state=SimpleNamespace()))
adapter = AdminProviderDeleteTaskStatusAdapter(provider_id="provider-1", task_id="task-1")
result = await adapter.handle(context)
assert result.task_id == "task-1"
assert result.status == "running"
assert result.stage == "deleting_keys"
assert result.deleted_keys == 25
assert result.deleted_endpoints == 2