Files
orion/tests/integration/api/v1/vendor/test_messages.py
Samir Boulahtit 0098093287 feat: enhance messaging system with improved API and tests
- Refactor messaging API endpoints for admin, shop, and vendor
- Add message-specific exceptions (ConversationNotFoundException, etc.)
- Enhance messaging service with additional helper methods
- Add comprehensive test fixtures for messaging
- Add integration tests for admin and vendor messaging APIs
- Add unit tests for messaging and attachment services

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 21:01:14 +01:00

257 lines
8.3 KiB
Python

# tests/integration/api/v1/vendor/test_messages.py
"""
Integration tests for vendor messaging endpoints.
Tests the /api/v1/vendor/messages/* endpoints.
"""
import pytest
from models.database.message import ConversationType, ParticipantType
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorMessagesListAPI:
"""Tests for vendor message list endpoints."""
def test_list_conversations_empty(self, client, vendor_user_headers):
"""Test listing conversations when none exist."""
response = client.get("/api/v1/vendor/messages", headers=vendor_user_headers)
assert response.status_code == 200
data = response.json()
assert "conversations" in data
assert "total" in data
assert "total_unread" in data
assert data["total"] == 0
def test_list_conversations_requires_auth(self, client):
"""Test that listing requires authentication."""
response = client.get("/api/v1/vendor/messages")
assert response.status_code == 401
def test_list_conversations_requires_vendor(self, client, admin_headers):
"""Test that admin cannot use vendor endpoint."""
response = client.get("/api/v1/vendor/messages", headers=admin_headers)
# Admin doesn't have vendor context
assert response.status_code == 403
def test_list_conversations_with_data(
self, client, vendor_user_headers, vendor_api_conversation
):
"""Test listing conversations with existing data."""
response = client.get("/api/v1/vendor/messages", headers=vendor_user_headers)
assert response.status_code == 200
data = response.json()
assert data["total"] >= 1
def test_list_conversations_filter_by_type(
self, client, vendor_user_headers, vendor_api_conversation
):
"""Test filtering conversations by type."""
response = client.get(
"/api/v1/vendor/messages",
params={"conversation_type": "admin_vendor"},
headers=vendor_user_headers,
)
assert response.status_code == 200
data = response.json()
for conv in data["conversations"]:
assert conv["conversation_type"] == "admin_vendor"
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorMessagesUnreadCountAPI:
"""Tests for unread count endpoint."""
def test_get_unread_count(self, client, vendor_user_headers):
"""Test getting unread count."""
response = client.get(
"/api/v1/vendor/messages/unread-count", headers=vendor_user_headers
)
assert response.status_code == 200
data = response.json()
assert "total_unread" in data
assert isinstance(data["total_unread"], int)
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorMessagesRecipientsAPI:
"""Tests for recipients endpoint."""
def test_get_customer_recipients(
self, client, vendor_user_headers, test_customer
):
"""Test getting customer recipients."""
response = client.get(
"/api/v1/vendor/messages/recipients",
params={"recipient_type": "customer"},
headers=vendor_user_headers,
)
assert response.status_code == 200
data = response.json()
assert "recipients" in data
assert "total" in data
def test_get_recipients_requires_type(self, client, vendor_user_headers):
"""Test that recipient_type is required."""
response = client.get(
"/api/v1/vendor/messages/recipients", headers=vendor_user_headers
)
assert response.status_code == 422
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorMessagesCreateAPI:
"""Tests for conversation creation."""
def test_create_conversation_vendor_customer(
self, client, vendor_user_headers, test_customer, test_vendor
):
"""Test creating vendor-customer conversation."""
response = client.post(
"/api/v1/vendor/messages",
json={
"conversation_type": "vendor_customer",
"subject": "Customer Support",
"recipient_type": "customer",
"recipient_id": test_customer.id,
"vendor_id": test_vendor.id,
"initial_message": "Hello customer!",
},
headers=vendor_user_headers,
)
assert response.status_code == 200
data = response.json()
assert data["subject"] == "Customer Support"
assert data["conversation_type"] == "vendor_customer"
def test_create_conversation_admin_vendor_not_allowed(
self, client, vendor_user_headers, test_admin, test_vendor
):
"""Test vendor cannot initiate admin_vendor conversation."""
response = client.post(
"/api/v1/vendor/messages",
json={
"conversation_type": "admin_vendor",
"subject": "Question for Admin",
"recipient_type": "admin",
"recipient_id": test_admin.id,
"vendor_id": test_vendor.id,
},
headers=vendor_user_headers,
)
assert response.status_code == 400
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorMessagesDetailAPI:
"""Tests for conversation detail."""
def test_get_conversation_detail(
self, client, vendor_user_headers, vendor_api_conversation
):
"""Test getting conversation detail."""
response = client.get(
f"/api/v1/vendor/messages/{vendor_api_conversation.id}",
headers=vendor_user_headers,
)
assert response.status_code == 200
data = response.json()
assert data["id"] == vendor_api_conversation.id
assert "participants" in data
assert "messages" in data
def test_get_conversation_not_found(self, client, vendor_user_headers):
"""Test getting nonexistent conversation."""
response = client.get(
"/api/v1/vendor/messages/99999", headers=vendor_user_headers
)
assert response.status_code == 404
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorMessagesSendAPI:
"""Tests for sending messages."""
def test_send_message(
self, client, vendor_user_headers, vendor_api_conversation
):
"""Test sending a message."""
response = client.post(
f"/api/v1/vendor/messages/{vendor_api_conversation.id}/messages",
data={"content": "Reply from vendor"},
headers=vendor_user_headers,
)
assert response.status_code == 200
data = response.json()
assert data["content"] == "Reply from vendor"
assert data["sender_type"] == "vendor"
def test_send_message_to_closed(
self, client, vendor_user_headers, vendor_api_closed_conversation
):
"""Test cannot send to closed conversation."""
response = client.post(
f"/api/v1/vendor/messages/{vendor_api_closed_conversation.id}/messages",
data={"content": "Test message"},
headers=vendor_user_headers,
)
assert response.status_code == 400
@pytest.mark.integration
@pytest.mark.api
@pytest.mark.vendor
class TestVendorMessagesActionsAPI:
"""Tests for conversation actions."""
def test_mark_read(
self, client, vendor_user_headers, vendor_api_conversation
):
"""Test marking conversation as read."""
response = client.put(
f"/api/v1/vendor/messages/{vendor_api_conversation.id}/read",
headers=vendor_user_headers,
)
assert response.status_code == 200
data = response.json()
assert data["success"] is True
assert data["unread_count"] == 0
def test_update_preferences(
self, client, vendor_user_headers, vendor_api_conversation
):
"""Test updating notification preferences."""
response = client.put(
f"/api/v1/vendor/messages/{vendor_api_conversation.id}/preferences",
json={"email_notifications": True, "muted": False},
headers=vendor_user_headers,
)
assert response.status_code == 200
data = response.json()
assert data["success"] is True