129 lines
4.3 KiB
Python
129 lines
4.3 KiB
Python
import pytest
|
|
from unittest.mock import patch, AsyncMock
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_feedback(client, auth_headers):
|
|
"""Test successful feedback submission — saves to DB and sends emails."""
|
|
with patch("app.api.endpoints.feedback.settings") as mock_settings, \
|
|
patch("app.api.endpoints.feedback.EmailService") as mock_email:
|
|
mock_settings.FEEDBACK_EMAIL = "support@test.com"
|
|
mock_email.send_feedback_email = AsyncMock(return_value=True)
|
|
mock_email.send_feedback_confirmation_email = AsyncMock(return_value=True)
|
|
|
|
response = await client.post(
|
|
"/api/v1/feedback",
|
|
json={
|
|
"email": "test@example.com",
|
|
"feedback_type": "Bug Report",
|
|
"message": "Something is broken in the tree editor when I try to save.",
|
|
},
|
|
headers=auth_headers,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["success"] is True
|
|
assert "submitted" in data["message"].lower()
|
|
|
|
# Verify both emails were called
|
|
mock_email.send_feedback_email.assert_called_once()
|
|
mock_email.send_feedback_confirmation_email.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_feedback_saves_to_db_even_if_email_fails(client, auth_headers, test_db):
|
|
"""Test that feedback is persisted even when email sending fails."""
|
|
from sqlalchemy import select, func
|
|
from app.models.feedback import Feedback
|
|
|
|
with patch("app.api.endpoints.feedback.settings") as mock_settings, \
|
|
patch("app.api.endpoints.feedback.EmailService") as mock_email:
|
|
mock_settings.FEEDBACK_EMAIL = "support@test.com"
|
|
mock_email.send_feedback_email = AsyncMock(return_value=False)
|
|
mock_email.send_feedback_confirmation_email = AsyncMock(return_value=False)
|
|
|
|
response = await client.post(
|
|
"/api/v1/feedback",
|
|
json={
|
|
"email": "test@example.com",
|
|
"feedback_type": "Feature Request",
|
|
"message": "Please add dark mode to the export preview screen.",
|
|
},
|
|
headers=auth_headers,
|
|
)
|
|
|
|
# Should still succeed — DB write happened
|
|
assert response.status_code == 200
|
|
assert response.json()["success"] is True
|
|
|
|
# Verify it was saved to the database
|
|
result = await test_db.execute(select(func.count()).select_from(Feedback))
|
|
count = result.scalar()
|
|
assert count >= 1
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_feedback_not_configured(client, auth_headers):
|
|
"""Test 503 when FEEDBACK_EMAIL is not set."""
|
|
with patch("app.api.endpoints.feedback.settings") as mock_settings:
|
|
mock_settings.FEEDBACK_EMAIL = None
|
|
|
|
response = await client.post(
|
|
"/api/v1/feedback",
|
|
json={
|
|
"email": "test@example.com",
|
|
"feedback_type": "General Feedback",
|
|
"message": "This is a general feedback message for testing.",
|
|
},
|
|
headers=auth_headers,
|
|
)
|
|
|
|
assert response.status_code == 503
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_feedback_validation_message_too_short(client, auth_headers):
|
|
"""Test validation — message too short."""
|
|
response = await client.post(
|
|
"/api/v1/feedback",
|
|
json={
|
|
"email": "test@example.com",
|
|
"feedback_type": "Bug Report",
|
|
"message": "short",
|
|
},
|
|
headers=auth_headers,
|
|
)
|
|
|
|
assert response.status_code == 422
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_feedback_invalid_type(client, auth_headers):
|
|
"""Test validation — invalid feedback type."""
|
|
response = await client.post(
|
|
"/api/v1/feedback",
|
|
json={
|
|
"email": "test@example.com",
|
|
"feedback_type": "Invalid Type",
|
|
"message": "This should fail because the type is invalid.",
|
|
},
|
|
headers=auth_headers,
|
|
)
|
|
|
|
assert response.status_code == 422
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_submit_feedback_requires_auth(client):
|
|
"""Test that unauthenticated requests are rejected."""
|
|
response = await client.post(
|
|
"/api/v1/feedback",
|
|
json={
|
|
"email": "anon@example.com",
|
|
"feedback_type": "General Feedback",
|
|
"message": "This should fail because I'm not logged in.",
|
|
},
|
|
)
|
|
assert response.status_code == 401
|