seller_central_backend/api/tests.py

238 lines
9 KiB
Python
Raw Normal View History

2026-08-09 06:12:43 +00:00
import pytest
from django.urls import reverse
from django.contrib.auth.models import User
from rest_framework import status
from rest_framework.test import APIClient
2026-08-12 07:51:11 +00:00
from api.models import Product, Order, ReturnRequest, Wallet, WalletTransaction, SupplierProfile
2026-08-09 06:12:43 +00:00
@pytest.fixture
def api_client():
return APIClient()
@pytest.fixture
def create_user(db):
2026-08-12 07:51:11 +00:00
user = User.objects.create_user(username='demo_seller', email='demo@example.com', password='Password123!')
SupplierProfile.objects.create(user=user, phone='1234567890')
Order.objects.create(
supplier=user,
order_id='OR-8721-demo',
date='2026-08-05',
item='Handmade Wool Blanket',
quantity=1,
customer='Alice Smith',
total=85.00,
status='Pending Acceptance'
)
ReturnRequest.objects.create(
supplier=user,
return_id='RET-5510-demo',
order_id='OR-3920-demo',
customer='Bob Johnson',
item='Silk Scarf',
reason='Ordered wrong color variant.',
status='Pending Approval'
)
2026-08-09 06:12:43 +00:00
return user
@pytest.mark.django_db
def test_user_registration(api_client):
url = reverse('register')
data = {
'username': 'new_seller',
'email': 'new@example.com',
'phone': '1234567890',
2026-08-12 07:51:11 +00:00
'password': 'SecurePassword123!'
2026-08-09 06:12:43 +00:00
}
response = api_client.post(url, data, format='json')
assert response.status_code == status.HTTP_201_CREATED
2026-08-12 07:51:11 +00:00
assert response.data['user']['username'] == 'new_seller'
2026-08-09 06:12:43 +00:00
assert User.objects.filter(username='new_seller').exists()
2026-08-10 12:31:54 +00:00
@pytest.mark.django_db
def test_user_logout(api_client, create_user):
url = reverse('logout')
api_client.force_authenticate(user=create_user)
response = api_client.post(url)
assert response.status_code == status.HTTP_200_OK
assert response.data['success'] is True
2026-08-09 06:12:43 +00:00
@pytest.mark.django_db
2026-08-12 07:51:11 +00:00
def test_otp_verification(api_client, create_user):
2026-08-09 06:12:43 +00:00
url = reverse('verify-otp')
2026-08-12 07:51:11 +00:00
api_client.force_authenticate(user=create_user)
2026-08-09 06:12:43 +00:00
# Correct OTP
2026-08-12 07:51:11 +00:00
response = api_client.post(url, {'type': 'phone', 'otp': '123456'}, format='json')
2026-08-09 06:12:43 +00:00
assert response.status_code == status.HTTP_200_OK
assert response.data['verified'] is True
# Incorrect OTP
2026-08-12 07:51:11 +00:00
response = api_client.post(url, {'type': 'phone', 'otp': '000000'}, format='json')
2026-08-09 06:12:43 +00:00
assert response.status_code == status.HTTP_400_BAD_REQUEST
assert response.data['verified'] is False
@pytest.mark.django_db
def test_profile_update(api_client, create_user):
url = reverse('profile')
api_client.force_authenticate(user=create_user)
data = {
'store_name': 'New Artisan Handloom',
'business_bio': 'Beautiful handmade rugs.',
'gstin': '29AAAAA1111A1Z1',
2026-08-12 07:51:11 +00:00
'is_gstin_verified': True,
'aadhar_s3_key': 'suppliers/1/aadhar.pdf',
'pan_s3_key': 'suppliers/1/pan.pdf',
'logo_s3_key': 'suppliers/1/logo.jpg',
'business_type': 'individual_maker',
'store_slug': 'new-artisan-handloom',
'categories': ['Sustainable Products', 'Home Decor']
2026-08-09 06:12:43 +00:00
}
response = api_client.put(url, data, format='json')
assert response.status_code == status.HTTP_200_OK
2026-08-12 07:51:11 +00:00
create_user.profile.refresh_from_db()
2026-08-09 06:12:43 +00:00
assert create_user.profile.store_name == 'New Artisan Handloom'
assert create_user.profile.is_gstin_verified is True
assert create_user.profile.business_type == 'individual_maker'
assert create_user.profile.store_slug == 'new-artisan-handloom'
assert set(create_user.profile.categories.values_list('name', flat=True)) == {'Sustainable Products', 'Home Decor'}
2026-08-09 06:12:43 +00:00
@pytest.mark.django_db
def test_product_crud(api_client, create_user):
api_client.force_authenticate(user=create_user)
# Create product
url = reverse('product-list')
data = {
'title': 'Test Indigo Shawl',
'category': 'Apparel',
'price': '85.00',
'stock': 10,
'sku': 'TEST-SHAWL-01'
}
response = api_client.post(url, data, format='json')
assert response.status_code == status.HTTP_201_CREATED
assert Product.objects.filter(sku='TEST-SHAWL-01').exists()
2026-08-12 07:51:11 +00:00
# List products (returns paginated structure under 'results')
2026-08-09 06:12:43 +00:00
response = api_client.get(url)
assert response.status_code == status.HTTP_200_OK
2026-08-12 07:51:11 +00:00
assert len(response.data['results']) == 1
2026-08-09 06:12:43 +00:00
@pytest.mark.django_db
def test_bulk_upload(api_client, create_user):
api_client.force_authenticate(user=create_user)
url = reverse('bulk-upload')
data = {
'products': [
{'title': 'Bulk Bowl', 'category': 'Kitchenware', 'price': '65.00', 'stock': 15, 'sku': 'BOWL-WAL-12'},
2026-08-12 07:51:11 +00:00
{'title': 'Bulk Tablecloth', 'category': 'Textiles', 'price': '48.00', 'stock': 30, 'sku': 'LINE-COT-15'}
2026-08-09 06:12:43 +00:00
]
}
response = api_client.post(url, data, format='json')
assert response.status_code == status.HTTP_200_OK
assert response.data['success'] is True
assert Product.objects.filter(sku='BOWL-WAL-12').exists()
assert Product.objects.filter(sku='LINE-COT-15').exists()
@pytest.mark.django_db
def test_order_actions(api_client, create_user):
api_client.force_authenticate(user=create_user)
# Query list to auto-create mock orders
list_url = reverse('order-list')
api_client.get(list_url)
order = Order.objects.filter(supplier=create_user, status='Pending Acceptance').first()
assert order is not None
# Accept order
accept_url = reverse('order-accept', args=[order.id])
response = api_client.post(accept_url)
assert response.status_code == status.HTTP_200_OK
assert response.data['status'] == 'Ready to Ship'
assert response.data['carrier'] == 'DHL Express'
@pytest.mark.django_db
def test_return_actions(api_client, create_user):
api_client.force_authenticate(user=create_user)
# Query list to auto-create mock return requests
list_url = reverse('return-list')
api_client.get(list_url)
ret = ReturnRequest.objects.filter(supplier=create_user, status='Pending Approval').first()
assert ret is not None
# Approve return
action_url = reverse('return-action', args=[ret.id])
response = api_client.post(action_url, {'action': 'Approved'}, format='json')
assert response.status_code == status.HTTP_200_OK
assert response.data['status'] == 'In Transit'
@pytest.mark.django_db
def test_wallet_withdrawal(api_client, create_user):
api_client.force_authenticate(user=create_user)
wallet = Wallet.objects.create(supplier=create_user, outstanding=1000.00, withdrawn=500.00)
url = reverse('withdraw')
# Successful withdrawal
response = api_client.post(url, {'amount': '200.00'}, format='json')
assert response.status_code == status.HTTP_200_OK
assert response.data['outstanding'] == '800.00'
assert response.data['withdrawn'] == '700.00'
assert WalletTransaction.objects.filter(wallet=wallet).exists()
# Invalid amount (exceeds outstanding)
response = api_client.post(url, {'amount': '1500.00'}, format='json')
assert response.status_code == status.HTTP_400_BAD_REQUEST
2026-08-20 05:51:14 +00:00
@pytest.mark.django_db
def test_document_cloudfront_url_generation(api_client, create_user):
from django.conf import settings
from api.views import get_document_url
profile = create_user.profile
profile.aadhar_s3_key = 'suppliers/123/aadhar.pdf'
profile.save()
# Case 1: CloudFront Domain set
settings.AWS_CLOUDFRONT_DOMAIN = 'd12345.cloudfront.net'
url = get_document_url(profile.aadhar_s3_key)
assert url == 'https://d12345.cloudfront.net/suppliers/123/aadhar.pdf'
# Case 2: CloudFront Domain set with protocol prefix
settings.AWS_CLOUDFRONT_DOMAIN = 'https://d98765.cloudfront.net/'
url = get_document_url(profile.aadhar_s3_key)
assert url == 'https://d98765.cloudfront.net/suppliers/123/aadhar.pdf'
# Case 3: CloudFront Domain empty, fallback to Local Mock
settings.AWS_CLOUDFRONT_DOMAIN = ''
url = get_document_url(profile.aadhar_s3_key)
assert 'mock-download' in url
# Case 4: API Response includes aadhar_url, pan_url, logo_url
url = reverse('profile')
api_client.force_authenticate(user=create_user)
response = api_client.get(url)
assert response.status_code == status.HTTP_200_OK
assert 'aadhar_url' in response.data['profile']
assert 'pan_url' in response.data['profile']
assert 'logo_url' in response.data['profile']
@pytest.mark.django_db
def test_mock_download_view(api_client, create_user):
api_client.force_authenticate(user=create_user)
# 1. Upload mock file first using PUT request
upload_url = reverse('mock-upload') + '?key=test_key.pdf'
file_content = b'PDF content'
upload_resp = api_client.put(upload_url, data=file_content, content_type='application/octet-stream')
assert upload_resp.status_code == status.HTTP_200_OK
# 2. Download it
download_url = reverse('mock-download') + '?key=test_key.pdf'
download_resp = api_client.get(download_url)
assert download_resp.status_code == status.HTTP_200_OK
assert b"".join(download_resp.streaming_content) == file_content