""" Brief API 集成测试 TDD 测试用例 - 测试 Brief 相关 API 接口 接口规范参考:DevelopmentPlan.md 第 7 章 """ import pytest from typing import Any from httpx import AsyncClient, ASGITransport from app.main import app @pytest.fixture async def auth_headers(): """获取认证头""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: login_response = await client.post("/api/v1/auth/login", json={ "email": "agency@test.com", "password": "password" }) token = login_response.json()["access_token"] return {"Authorization": f"Bearer {token}"} class TestBriefUploadAPI: """Brief 上传 API 测试""" @pytest.mark.integration @pytest.mark.asyncio async def test_upload_brief_pdf_success(self, auth_headers) -> None: """测试 Brief PDF 上传成功""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.post( "/api/v1/briefs/upload", files={"file": ("brief.pdf", b"PDF content", "application/pdf")}, data={"task_id": "task_001", "platform": "douyin"}, headers=auth_headers ) assert response.status_code == 202 data = response.json() assert "parsing_id" in data assert data["status"] == "processing" @pytest.mark.integration @pytest.mark.asyncio async def test_upload_unsupported_format_returns_400(self, auth_headers) -> None: """测试不支持的格式返回 400""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.post( "/api/v1/briefs/upload", files={"file": ("test.exe", b"content", "application/octet-stream")}, data={"task_id": "task_001"}, headers=auth_headers ) assert response.status_code == 400 assert "Unsupported file format" in response.json()["detail"] @pytest.mark.integration @pytest.mark.asyncio async def test_upload_without_auth_returns_401(self) -> None: """测试无认证返回 401""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.post( "/api/v1/briefs/upload", files={"file": ("brief.pdf", b"content", "application/pdf")}, data={"task_id": "task_001"} ) assert response.status_code == 401 class TestBriefParsingAPI: """Brief 解析结果 API 测试""" @pytest.mark.integration @pytest.mark.asyncio async def test_get_parsing_result_success(self, auth_headers) -> None: """测试获取解析结果成功""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.get( "/api/v1/briefs/brief_001", headers=auth_headers ) assert response.status_code == 200 data = response.json() assert "selling_points" in data assert "forbidden_words" in data assert "brand_tone" in data @pytest.mark.integration @pytest.mark.asyncio async def test_get_nonexistent_brief_returns_404(self, auth_headers) -> None: """测试获取不存在的 Brief 返回 404""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.get( "/api/v1/briefs/nonexistent_id", headers=auth_headers ) assert response.status_code == 404 class TestOnlineDocumentImportAPI: """在线文档导入 API 测试""" @pytest.mark.integration @pytest.mark.asyncio async def test_import_feishu_doc_success(self, auth_headers) -> None: """测试飞书文档导入成功""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.post( "/api/v1/briefs/import", json={ "url": "https://docs.feishu.cn/docs/valid_doc_id", "task_id": "task_001" }, headers=auth_headers ) assert response.status_code == 202 @pytest.mark.integration @pytest.mark.asyncio async def test_import_unauthorized_link_returns_403(self, auth_headers) -> None: """测试无权限链接返回 403""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.post( "/api/v1/briefs/import", json={ "url": "https://docs.feishu.cn/docs/restricted_doc", "task_id": "task_001" }, headers=auth_headers ) assert response.status_code == 403 class TestRuleConflictAPI: """规则冲突检测 API 测试""" @pytest.mark.integration @pytest.mark.asyncio async def test_detect_rule_conflict(self, auth_headers) -> None: """测试规则冲突检测""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.post( "/api/v1/briefs/brief_001/check_conflicts", json={"platform": "douyin"}, headers=auth_headers ) assert response.status_code == 200 data = response.json() assert "conflicts" in data