Files
zhangmenu/menu/tests.py
T
DeveloperandClaude Opus 4.6 0a50c09dba Initial commit - Zhangmenu Django project
A menu management application built with Django, featuring:
- Dish management with cover images
- Order system with party dates and participants
- REST API with Django REST Framework
- Bootstrap-styled frontend

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:27:23 +08:00

97 lines
3.8 KiB
Python

import json
from pathlib import Path
from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase, override_settings
from django.urls import reverse
from menu.models import Dish, DishCategory, Order
TEST_MEDIA_ROOT = Path(settings.BASE_DIR) / 'test_media'
@override_settings(MEDIA_ROOT=TEST_MEDIA_ROOT)
class UploadImageTests(TestCase):
def tearDown(self):
if TEST_MEDIA_ROOT.exists():
for path in sorted(TEST_MEDIA_ROOT.rglob('*'), reverse=True):
if path.is_file():
path.unlink()
elif path.is_dir():
path.rmdir()
def test_upload_rejects_invalid_extension(self):
image = SimpleUploadedFile('bad.txt', b'file-content', content_type='image/png')
response = self.client.post(reverse('upload'), {'image': image})
self.assertEqual(response.status_code, 400)
self.assertEqual(response.json()['error'], 'Unsupported image extension')
def test_upload_rejects_invalid_content_type(self):
image = SimpleUploadedFile('dish.png', b'file-content', content_type='text/plain')
response = self.client.post(reverse('upload'), {'image': image})
self.assertEqual(response.status_code, 400)
self.assertEqual(response.json()['error'], 'Unsupported image content type')
@override_settings(MAX_UPLOAD_IMAGE_SIZE=4)
def test_upload_rejects_oversized_file(self):
image = SimpleUploadedFile('dish.png', b'12345', content_type='image/png')
response = self.client.post(reverse('upload'), {'image': image})
self.assertEqual(response.status_code, 400)
self.assertEqual(response.json()['error'], 'Image file too large')
def test_upload_returns_absolute_media_url(self):
image = SimpleUploadedFile('dish.png', b'png-bytes', content_type='image/png')
response = self.client.post(reverse('upload'), {'image': image}, secure=True)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertTrue(data['url'].startswith('https://testserver/media/dishes/'))
class ParseUrlTests(TestCase):
def test_parse_url_rejects_non_allowlisted_host(self):
response = self.client.post(
'/api/parse-url/',
data=json.dumps({'url': 'http://127.0.0.1/internal'}),
content_type='application/json',
)
self.assertEqual(response.status_code, 400)
self.assertEqual(response.json()['error'], '该站点不在允许的解析范围内')
class OrderApiTests(TestCase):
def setUp(self):
category = DishCategory.objects.create(name='热菜')
self.dish1 = Dish.objects.create(name='宫保鸡丁', category=category, ingredients=[{'name': '鸡肉', 'amount': '300g'}])
self.dish2 = Dish.objects.create(name='鱼香肉丝', category=category, ingredients=[{'name': '猪肉', 'amount': '200g'}])
def test_create_order_binds_dish_ids_and_returns_saved_object(self):
payload = {
'name': '周末聚会',
'dish_ids': [self.dish1.id, self.dish2.id],
'participants': ['张三', '李四'],
'party_date': '2026-03-10T12:30:00Z',
}
response = self.client.post('/api/orders/', payload, content_type='application/json')
self.assertEqual(response.status_code, 201)
data = response.json()
self.assertEqual(data['name'], '周末聚会')
self.assertEqual(sorted(d['id'] for d in data['dishes_detail']), sorted([self.dish1.id, self.dish2.id]))
self.assertEqual(data['participants'], ['张三', '李四'])
order = Order.objects.get(pk=data['id'])
self.assertEqual(order.dishes.count(), 2)
self.assertEqual(sorted(order.dishes.values_list('id', flat=True)), sorted([self.dish1.id, self.dish2.id]))