Spaces:
Sleeping
Sleeping
| """ | |
| Comprehensive Tests for Contact Router | |
| Tests cover: | |
| 1. POST /contact - Contact form submission | |
| 2. Authentication requirements | |
| 3. Data validation | |
| 4. Rate limiting | |
| 5. Email notification (mocked) | |
| Uses mocked database and user authentication. | |
| """ | |
| import pytest | |
| from unittest.mock import MagicMock, AsyncMock, patch | |
| from fastapi.testclient import TestClient | |
| from fastapi import FastAPI | |
| # ============================================================================ | |
| # 1. Contact Form Submission Tests | |
| # ============================================================================ | |
| class TestContactSubmission: | |
| """Test contact form submission.""" | |
| def test_contact_requires_auth(self): | |
| """Contact endpoint requires authentication.""" | |
| from routers.contact import router | |
| app = FastAPI() | |
| app.include_router(router) | |
| client = TestClient(app) | |
| response = client.post("/contact", json={"message": "Test"}) | |
| # Should fail without auth (500 because no request.state.user) | |
| assert response.status_code == 500 | |
| def test_submit_contact_with_auth(self): | |
| """Authenticated users can submit contact forms.""" | |
| from routers.contact import router | |
| from core.database import get_db | |
| app = FastAPI() | |
| # Mock user | |
| mock_user = MagicMock() | |
| mock_user.id = 1 | |
| mock_user.user_id = "usr_contact" | |
| mock_user.email = "user@example.com" | |
| # Mock database | |
| async def mock_get_db(): | |
| mock_db = AsyncMock() | |
| yield mock_db | |
| # Middleware to set user | |
| async def add_user(request, call_next): | |
| request.state.user = mock_user | |
| return await call_next(request) | |
| app.dependency_overrides[get_db] = mock_get_db | |
| app.include_router(router) | |
| client = TestClient(app) | |
| response = client.post( | |
| "/contact", | |
| json={ | |
| "subject": "Help needed", | |
| "message": "I need assistance with my account" | |
| } | |
| ) | |
| assert response.status_code == 200 | |
| data = response.json() | |
| assert data["success"] == True | |
| def test_contact_with_subject(self): | |
| """Can submit contact with subject.""" | |
| from routers.contact import router | |
| from core.database import get_db | |
| app = FastAPI() | |
| mock_user = MagicMock() | |
| mock_user.id = 1 | |
| mock_user.email = "user@example.com" | |
| async def mock_get_db(): | |
| yield AsyncMock() | |
| async def add_user(request, call_next): | |
| request.state.user = mock_user | |
| return await call_next(request) | |
| app.dependency_overrides[get_db] = mock_get_db | |
| app.include_router(router) | |
| client = TestClient(app) | |
| response = client.post( | |
| "/contact", | |
| json={ | |
| "subject": "Bug report", | |
| "message": "Found a bug in the app" | |
| } | |
| ) | |
| assert response.status_code == 200 | |
| def test_contact_without_subject(self): | |
| """Can submit contact without subject.""" | |
| from routers.contact import router | |
| from core.database import get_db | |
| app = FastAPI() | |
| mock_user = MagicMock() | |
| mock_user.id = 1 | |
| mock_user.email = "user@example.com" | |
| async def mock_get_db(): | |
| yield AsyncMock() | |
| async def add_user(request, call_next): | |
| request.state.user = mock_user | |
| return await call_next(request) | |
| app.dependency_overrides[get_db] = mock_get_db | |
| app.include_router(router) | |
| client = TestClient(app) | |
| response = client.post( | |
| "/contact", | |
| json={"message": "Just wanted to say hello!"} | |
| ) | |
| assert response.status_code == 200 | |
| # ============================================================================ | |
| # 2. Data Validation Tests | |
| # ============================================================================ | |
| class TestContactValidation: | |
| """Test contact form data validation.""" | |
| def test_empty_message_rejected(self): | |
| """Empty message is rejected.""" | |
| from routers.contact import router | |
| from core.database import get_db | |
| app = FastAPI() | |
| mock_user = MagicMock() | |
| mock_user.id = 1 | |
| mock_user.email = "user@example.com" | |
| async def mock_get_db(): | |
| yield AsyncMock() | |
| async def add_user(request, call_next): | |
| request.state.user = mock_user | |
| return await call_next(request) | |
| app.dependency_overrides[get_db] = mock_get_db | |
| app.include_router(router) | |
| client = TestClient(app) | |
| response = client.post("/contact", json={"message": ""}) | |
| assert response.status_code == 400 | |
| def test_whitespace_only_message_rejected(self): | |
| """Whitespace-only message is rejected.""" | |
| from routers.contact import router | |
| from core.database import get_db | |
| app = FastAPI() | |
| mock_user = MagicMock() | |
| mock_user.id = 1 | |
| mock_user.email = "user@example.com" | |
| async def mock_get_db(): | |
| yield AsyncMock() | |
| async def add_user(request, call_next): | |
| request.state.user = mock_user | |
| return await call_next(request) | |
| app.dependency_overrides[get_db] = mock_get_db | |
| app.include_router(router) | |
| client = TestClient(app) | |
| response = client.post("/contact", json={"message": " "}) | |
| assert response.status_code == 400 | |
| # ============================================================================ | |
| # 3. Contact Storage Tests | |
| # ============================================================================ | |
| class TestContactStorage: | |
| """Test contact form storage in database.""" | |
| async def test_contact_stored_in_database(self, db_session): | |
| """Contact form is stored in database.""" | |
| from core.models import User, Contact | |
| from sqlalchemy import select | |
| # Create user | |
| user = User(user_id="usr_store", email="store@example.com") | |
| db_session.add(user) | |
| await db_session.commit() | |
| # Create contact | |
| contact = Contact( | |
| user_id=user.id, | |
| email=user.email, | |
| subject="Test subject", | |
| message="Test message", | |
| ip_address="192.168.1.1" | |
| ) | |
| db_session.add(contact) | |
| await db_session.commit() | |
| # Verify stored | |
| result = await db_session.execute( | |
| select(Contact).where(Contact.user_id == user.id) | |
| ) | |
| stored = result.scalar_one_or_none() | |
| assert stored is not None | |
| assert stored.message == "Test message" | |
| if __name__ == "__main__": | |
| pytest.main([__file__, "-v"]) | |