Files
wecom_it_smart_desk/backend/tests/test_agents_auth.py
T

214 lines
7.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# 企微IT智能服务台 — 坐席认证与管理测试
# =============================================================================
# 测试覆盖:
# 1. 坐席登录(新坐席注册 + 已有坐席重新登录)
# 2. Token 存 Redis(验证 TTL 和格式)
# 3. 获取当前坐席信息(有效 Token / 无效 Token / 过期 Token
# 4. 更新坐席状态(online/busy/offline
# 5. 无效状态值校验
# 6. 获取坐席列表
# 7. 缺少 Authorization 头返回未授权
# =============================================================================
import pytest
import pytest_asyncio
from unittest.mock import patch
from app.models.agent import Agent
from tests.conftest import create_test_agent, MockRedis
class TestAgentLogin:
"""测试坐席登录。"""
@pytest.mark.asyncio
async def test_login_new_agent(self, client, db_session, mock_redis):
"""验证新坐席首次登录自动注册。"""
response = await client.post(
"/agents/login",
json={"user_id": "new_agent_001", "name": "新坐席"},
)
assert response.status_code == 200
data = response.json()
assert data["code"] == 0
assert data["data"]["user_id"] == "new_agent_001"
assert data["data"]["name"] == "新坐席"
assert data["data"]["status"] == "online"
assert "token" in data["data"]
@pytest.mark.asyncio
async def test_login_existing_agent(self, client, db_session, mock_redis):
"""验证已有坐席重新登录更新信息。"""
# 先创建坐席
agent = create_test_agent(user_id="exist_agent", name="旧名字")
db_session.add(agent)
await db_session.flush()
response = await client.post(
"/agents/login",
json={"user_id": "exist_agent", "name": "新名字"},
)
assert response.status_code == 200
data = response.json()
assert data["data"]["name"] == "新名字"
assert data["data"]["status"] == "online"
@pytest.mark.asyncio
async def test_login_returns_token(self, client, db_session, mock_redis):
"""验证登录返回 Token 存入 Redis。"""
response = await client.post(
"/agents/login",
json={"user_id": "token_test_agent", "name": "Token测试"},
)
data = response.json()
assert "token" in data["data"]
# 验证 Redis 中存储了 tokenkey 格式:agent:token:{token}
token = data["data"]["token"]
redis_key = f"agent:token:{token}"
stored_value = await mock_redis.get(redis_key)
assert stored_value is not None
class TestAgentAuthentication:
"""测试坐席认证。"""
@pytest.mark.asyncio
async def test_get_agent_me_with_valid_token(self, client, db_session, mock_redis):
"""验证有效 Token 获取坐席信息。"""
# 先登录获取 token
login_resp = await client.post(
"/agents/login",
json={"user_id": "me_test_agent", "name": "我测试"},
)
token = login_resp.json()["data"]["token"]
# 用 token 获取坐席信息
response = await client.get(
"/agents/me",
headers={"Authorization": f"Bearer {token}"},
)
assert response.status_code == 200
data = response.json()
assert data["code"] == 0
assert data["data"]["user_id"] == "me_test_agent"
@pytest.mark.asyncio
async def test_get_agent_me_without_token(self, client, db_session, mock_redis):
"""验证缺少 Token 返回未授权。"""
response = await client.get("/agents/me")
data = response.json()
assert data["code"] == 1002 # ERR_UNAUTHORIZED
@pytest.mark.asyncio
async def test_get_agent_me_with_invalid_token(self, client, db_session, mock_redis):
"""验证无效 Token 返回未授权。"""
response = await client.get(
"/agents/me",
headers={"Authorization": "Bearer invalid_token_12345"},
)
data = response.json()
assert data["code"] == 1002
class TestAgentStatusUpdate:
"""测试坐席状态更新。"""
@pytest.mark.asyncio
async def test_update_status_to_busy(self, client, db_session, mock_redis):
"""验证更新坐席状态为忙碌。"""
# 先登录
login_resp = await client.post(
"/agents/login",
json={"user_id": "status_test_agent", "name": "状态测试"},
)
token = login_resp.json()["data"]["token"]
# 更新状态
response = await client.put(
"/agents/me/status",
json={"status": "busy"},
headers={"Authorization": f"Bearer {token}"},
)
assert response.status_code == 200
data = response.json()
assert data["data"]["status"] == "busy"
@pytest.mark.asyncio
async def test_update_status_to_offline(self, client, db_session, mock_redis):
"""验证更新坐席状态为离线。"""
login_resp = await client.post(
"/agents/login",
json={"user_id": "offline_test_agent", "name": "离线测试"},
)
token = login_resp.json()["data"]["token"]
response = await client.put(
"/agents/me/status",
json={"status": "offline"},
headers={"Authorization": f"Bearer {token}"},
)
data = response.json()
assert data["data"]["status"] == "offline"
@pytest.mark.asyncio
async def test_update_status_invalid_value(self, client, db_session, mock_redis):
"""验证无效状态值返回校验错误。"""
login_resp = await client.post(
"/agents/login",
json={"user_id": "invalid_status_agent", "name": "无效状态测试"},
)
token = login_resp.json()["data"]["token"]
response = await client.put(
"/agents/me/status",
json={"status": "invalid_status"},
headers={"Authorization": f"Bearer {token}"},
)
# Pydantic 校验应返回 422
assert response.status_code == 422
class TestAgentList:
"""测试坐席列表。"""
@pytest.mark.asyncio
async def test_list_agents(self, client, db_session, mock_redis):
"""验证获取坐席列表。"""
agent1 = create_test_agent(user_id="list_agent_1", name="坐席一")
agent2 = create_test_agent(user_id="list_agent_2", name="坐席二")
db_session.add_all([agent1, agent2])
await db_session.flush()
response = await client.get("/agents")
assert response.status_code == 200
data = response.json()
assert data["code"] == 0
assert len(data["data"]["items"]) >= 2
@pytest.mark.asyncio
async def test_list_agents_by_status(self, client, db_session, mock_redis):
"""验证按状态过滤坐席列表。"""
online_agent = create_test_agent(user_id="online_filter_agent", name="在线坐席", status="online")
offline_agent = create_test_agent(user_id="offline_filter_agent", name="离线坐席", status="offline")
db_session.add_all([online_agent, offline_agent])
await db_session.flush()
response = await client.get("/agents?status=online")
data = response.json()
assert data["code"] == 0
for item in data["data"]["items"]:
assert item["status"] == "online"