import pytest from httpx import AsyncClient from app.models.notification import Notification from app.models.feedback import Feedback class TestNotificationAPI: async def test_list_notifications_empty(self, client: AsyncClient, auth_headers): response = await client.get("/api/v1/notifications", headers=auth_headers) assert response.status_code == 200 data = response.json() assert "items" in data assert data["items"] == [] async def test_unread_count_zero(self, client: AsyncClient, auth_headers): response = await client.get("/api/v1/notifications/unread-count", headers=auth_headers) assert response.status_code == 200 assert response.json()["count"] == 0 async def test_create_and_list_notification(self, client: AsyncClient, auth_headers, db_session, test_user): n = Notification( user_id=test_user.id, title="Test Title", content="Test Content", ) db_session.add(n) await db_session.commit() response = await client.get("/api/v1/notifications", headers=auth_headers) assert response.status_code == 200 data = response.json() assert len(data["items"]) >= 1 assert data["items"][0]["title"] == "Test Title" async def test_mark_read(self, client: AsyncClient, auth_headers, db_session, test_user): n = Notification(user_id=test_user.id, title="Read Test", content="Content") db_session.add(n) await db_session.commit() response = await client.patch( f"/api/v1/notifications/{n.id}/read", headers=auth_headers, ) assert response.status_code == 200 count_resp = await client.get("/api/v1/notifications/unread-count", headers=auth_headers) assert count_resp.json()["count"] == 0 async def test_mark_all_read(self, client: AsyncClient, auth_headers, db_session, test_user): for i in range(3): db_session.add(Notification(user_id=test_user.id, title=f"Notif {i}", content="Content")) await db_session.commit() response = await client.post("/api/v1/notifications/read-all", headers=auth_headers) assert response.status_code == 200 assert response.json()["count"] == 3 async def test_delete_notification(self, client: AsyncClient, auth_headers, db_session, test_user): n = Notification(user_id=test_user.id, title="Delete Me", content="Content") db_session.add(n) await db_session.commit() nid = n.id response = await client.delete(f"/api/v1/notifications/{nid}", headers=auth_headers) assert response.status_code == 200 list_resp = await client.get("/api/v1/notifications", headers=auth_headers) ids = [item["id"] for item in list_resp.json()["items"]] assert str(nid) not in ids async def test_delete_not_found(self, client: AsyncClient, auth_headers): import uuid response = await client.delete( f"/api/v1/notifications/{uuid.uuid4()}", headers=auth_headers, ) assert response.status_code == 404 async def test_unread_count_after_read(self, client: AsyncClient, auth_headers, db_session, test_user): for i in range(2): db_session.add(Notification(user_id=test_user.id, title=f"Unread {i}", content="C")) await db_session.commit() resp = await client.get("/api/v1/notifications/unread-count", headers=auth_headers) assert resp.json()["count"] == 2 async def test_unread_only_filter(self, client: AsyncClient, auth_headers, db_session, test_user): n1 = Notification(user_id=test_user.id, title="Read", content="C", is_read=True) n2 = Notification(user_id=test_user.id, title="Unread", content="C") db_session.add_all([n1, n2]) await db_session.commit() response = await client.get( "/api/v1/notifications?unread_only=true", headers=auth_headers, ) assert response.status_code == 200 for item in response.json()["items"]: assert item["is_read"] is False class TestFeedbackAPI: async def test_submit_feedback(self, client: AsyncClient, auth_headers): response = await client.post( "/api/v1/feedback", headers=auth_headers, json={ "content": "Great app!", "category": "feature", "contact": "test@example.com", }, ) assert response.status_code == 200 assert response.json()["status"] == "ok" async def test_submit_feedback_minimal(self, client: AsyncClient, auth_headers): response = await client.post( "/api/v1/feedback", headers=auth_headers, json={"content": "Bug report"}, ) assert response.status_code == 200 assert response.json()["status"] == "ok" async def test_submit_feedback_unauthorized(self, client: AsyncClient): response = await client.post( "/api/v1/feedback", json={"content": "Test"}, ) assert response.status_code == 401 class TestPaymentAPI: async def test_get_plans(self, client: AsyncClient, auth_headers): response = await client.get("/api/v1/payment/plans", headers=auth_headers) assert response.status_code == 200 data = response.json() assert "plans" in data assert len(data["plans"]) >= 3 async def test_get_subscription_free(self, client: AsyncClient, auth_headers): response = await client.get("/api/v1/payment/subscription", headers=auth_headers) assert response.status_code == 200 data = response.json() assert "plan" in data assert "status" in data async def test_create_order(self, client: AsyncClient, auth_headers): response = await client.post( "/api/v1/payment/create-order", headers=auth_headers, json={"plan": "pro"}, ) assert response.status_code == 200 data = response.json() assert "prepay_id" in data or "order_id" in data or "url" in data