mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Fixes:
- Use DRF ImageField, not FileField - Ensure that permissions get updated correctly in 'test' mode - Allow file upload in the APITester class
This commit is contained in:
parent
a866001ffe
commit
5ba7aeaa27
3
.gitignore
vendored
3
.gitignore
vendored
@ -35,6 +35,9 @@ local_settings.py
|
|||||||
*.backup
|
*.backup
|
||||||
*.old
|
*.old
|
||||||
|
|
||||||
|
# Files used for testing
|
||||||
|
dummy_image.*
|
||||||
|
|
||||||
# Sphinx files
|
# Sphinx files
|
||||||
docs/_build
|
docs/_build
|
||||||
|
|
||||||
|
@ -109,12 +109,12 @@ class InvenTreeAPITestCase(APITestCase):
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def patch(self, url, data, expected_code=None):
|
def patch(self, url, data, files=None, expected_code=None):
|
||||||
"""
|
"""
|
||||||
Issue a PATCH request
|
Issue a PATCH request
|
||||||
"""
|
"""
|
||||||
|
|
||||||
response = self.client.patch(url, data=data, format='json')
|
response = self.client.patch(url, data=data, files=files, format='json')
|
||||||
|
|
||||||
if expected_code is not None:
|
if expected_code is not None:
|
||||||
self.assertEqual(response.status_code, expected_code)
|
self.assertEqual(response.status_code, expected_code)
|
||||||
|
@ -12,7 +12,7 @@ def isInTestMode():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def canAppAccessDatabase():
|
def canAppAccessDatabase(allow_test=False):
|
||||||
"""
|
"""
|
||||||
Returns True if the apps.py file can access database records.
|
Returns True if the apps.py file can access database records.
|
||||||
|
|
||||||
@ -39,6 +39,10 @@ def canAppAccessDatabase():
|
|||||||
'compilemessages',
|
'compilemessages',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if not allow_test:
|
||||||
|
# Override for testing mode?
|
||||||
|
excluded_commands.append('test')
|
||||||
|
|
||||||
for cmd in excluded_commands:
|
for cmd in excluded_commands:
|
||||||
if cmd in sys.argv:
|
if cmd in sys.argv:
|
||||||
return False
|
return False
|
||||||
|
@ -103,7 +103,7 @@ class InvenTreeAttachmentSerializerField(serializers.FileField):
|
|||||||
return os.path.join(str(settings.MEDIA_URL), str(value))
|
return os.path.join(str(settings.MEDIA_URL), str(value))
|
||||||
|
|
||||||
|
|
||||||
class InvenTreeImageSerializerField(serializers.FileField):
|
class InvenTreeImageSerializerField(serializers.ImageField):
|
||||||
"""
|
"""
|
||||||
Custom image serializer.
|
Custom image serializer.
|
||||||
On upload, validate that the file is a valid image file
|
On upload, validate that the file is a valid image file
|
||||||
|
@ -31,8 +31,6 @@ v3 -> 2021-05-22:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def inventreeInstanceName():
|
def inventreeInstanceName():
|
||||||
""" Returns the InstanceName settings for the current database """
|
""" Returns the InstanceName settings for the current database """
|
||||||
return common.models.InvenTreeSetting.get_setting("INVENTREE_INSTANCE", "")
|
return common.models.InvenTreeSetting.get_setting("INVENTREE_INSTANCE", "")
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from rest_framework import status
|
import PIL
|
||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.test import APIClient
|
||||||
|
|
||||||
|
from InvenTree.api_tester import InvenTreeAPITestCase
|
||||||
|
from InvenTree.status_codes import StockStatus
|
||||||
|
|
||||||
from part.models import Part, PartCategory
|
from part.models import Part, PartCategory
|
||||||
from stock.models import StockItem
|
from stock.models import StockItem
|
||||||
from company.models import Company
|
from company.models import Company
|
||||||
|
|
||||||
from InvenTree.api_tester import InvenTreeAPITestCase
|
|
||||||
from InvenTree.status_codes import StockStatus
|
|
||||||
|
|
||||||
|
|
||||||
class PartAPITest(InvenTreeAPITestCase):
|
class PartAPITest(InvenTreeAPITestCase):
|
||||||
"""
|
"""
|
||||||
@ -473,6 +476,74 @@ class PartDetailTests(InvenTreeAPITestCase):
|
|||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
def test_image_upload(self):
|
||||||
|
"""
|
||||||
|
Test that we can upload an image to the part API
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assignRole('part.add')
|
||||||
|
|
||||||
|
# Create a new part
|
||||||
|
response = self.client.post(
|
||||||
|
reverse('api-part-list'),
|
||||||
|
{
|
||||||
|
'name': 'imagine',
|
||||||
|
'description': 'All the people',
|
||||||
|
'category': 1,
|
||||||
|
},
|
||||||
|
expected_code=201
|
||||||
|
)
|
||||||
|
|
||||||
|
pk = response.data['pk']
|
||||||
|
|
||||||
|
url = reverse('api-part-detail', kwargs={'pk': pk})
|
||||||
|
|
||||||
|
p = Part.objects.get(pk=pk)
|
||||||
|
|
||||||
|
# Part should not have an image!
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
print(p.image.file)
|
||||||
|
|
||||||
|
# Create a custom APIClient for file uploads
|
||||||
|
# Ref: https://stackoverflow.com/questions/40453947/how-to-generate-a-file-upload-test-request-with-django-rest-frameworks-apireq
|
||||||
|
upload_client = APIClient()
|
||||||
|
upload_client.force_authenticate(user=self.user)
|
||||||
|
|
||||||
|
# Try to upload a non-image file
|
||||||
|
with open('dummy_image.txt', 'w') as dummy_image:
|
||||||
|
dummy_image.write('hello world')
|
||||||
|
|
||||||
|
with open('dummy_image.txt', 'rb') as dummy_image:
|
||||||
|
response = upload_client.patch(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
'image': dummy_image,
|
||||||
|
},
|
||||||
|
format='multipart',
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 400)
|
||||||
|
|
||||||
|
# Now try to upload a valid image file
|
||||||
|
img = PIL.Image.new('RGB', (128, 128), color='red')
|
||||||
|
img.save('dummy_image.jpg')
|
||||||
|
|
||||||
|
with open('dummy_image.jpg', 'rb') as dummy_image:
|
||||||
|
response = upload_client.patch(
|
||||||
|
url,
|
||||||
|
{
|
||||||
|
'image': dummy_image,
|
||||||
|
},
|
||||||
|
format='multipart',
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# And now check that the image has been set
|
||||||
|
p = Part.objects.get(pk=pk)
|
||||||
|
|
||||||
|
print("Image:", p.image.file)
|
||||||
|
|
||||||
|
|
||||||
class PartAPIAggregationTest(InvenTreeAPITestCase):
|
class PartAPIAggregationTest(InvenTreeAPITestCase):
|
||||||
"""
|
"""
|
||||||
|
@ -13,7 +13,7 @@ class UsersConfig(AppConfig):
|
|||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
|
||||||
if canAppAccessDatabase():
|
if canAppAccessDatabase(allow_test=True):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.assign_permissions()
|
self.assign_permissions()
|
||||||
|
@ -276,7 +276,7 @@ def update_group_roles(group, debug=False):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not canAppAccessDatabase():
|
if not canAppAccessDatabase(allow_test=True):
|
||||||
return
|
return
|
||||||
|
|
||||||
# List of permissions already associated with this group
|
# List of permissions already associated with this group
|
||||||
|
Loading…
Reference in New Issue
Block a user