mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge pull request #1700 from SchrodingersGat/api-default-values
Unit testing for default values
This commit is contained in:
commit
9e720ea620
@ -18,6 +18,7 @@ class InvenTreeAPITestCase(APITestCase):
|
||||
email = 'test@testing.com'
|
||||
|
||||
superuser = False
|
||||
is_staff = True
|
||||
auto_login = True
|
||||
|
||||
# Set list of roles automatically associated with the user
|
||||
@ -40,8 +41,12 @@ class InvenTreeAPITestCase(APITestCase):
|
||||
|
||||
if self.superuser:
|
||||
self.user.is_superuser = True
|
||||
self.user.save()
|
||||
|
||||
if self.is_staff:
|
||||
self.user.is_staff = True
|
||||
|
||||
self.user.save()
|
||||
|
||||
for role in self.roles:
|
||||
self.assignRole(role)
|
||||
|
||||
|
@ -2,17 +2,19 @@
|
||||
Serializers used in various InvenTree apps
|
||||
"""
|
||||
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||
|
||||
from rest_framework import serializers
|
||||
from rest_framework.utils import model_meta
|
||||
from rest_framework.fields import empty
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
@ -42,6 +44,72 @@ class InvenTreeModelSerializer(serializers.ModelSerializer):
|
||||
but also ensures that the underlying model class data are checked on validation.
|
||||
"""
|
||||
|
||||
def __init__(self, instance=None, data=empty, **kwargs):
|
||||
|
||||
self.instance = instance
|
||||
|
||||
# If instance is None, we are creating a new instance
|
||||
if instance is None:
|
||||
|
||||
if data is empty:
|
||||
data = OrderedDict()
|
||||
else:
|
||||
# Required to side-step immutability of a QueryDict
|
||||
data = data.copy()
|
||||
|
||||
# Add missing fields which have default values
|
||||
ModelClass = self.Meta.model
|
||||
|
||||
fields = model_meta.get_field_info(ModelClass)
|
||||
|
||||
for field_name, field in fields.fields.items():
|
||||
|
||||
if field.has_default() and field_name not in data:
|
||||
|
||||
value = field.default
|
||||
|
||||
# Account for callable functions
|
||||
if callable(value):
|
||||
try:
|
||||
value = value()
|
||||
except:
|
||||
continue
|
||||
|
||||
data[field_name] = value
|
||||
|
||||
super().__init__(instance, data, **kwargs)
|
||||
|
||||
def get_initial(self):
|
||||
"""
|
||||
Construct initial data for the serializer.
|
||||
Use the 'default' values specified by the django model definition
|
||||
"""
|
||||
|
||||
initials = super().get_initial()
|
||||
|
||||
# Are we creating a new instance?
|
||||
if self.instance is None:
|
||||
ModelClass = self.Meta.model
|
||||
|
||||
fields = model_meta.get_field_info(ModelClass)
|
||||
|
||||
for field_name, field in fields.fields.items():
|
||||
|
||||
if field.has_default() and field_name not in initials:
|
||||
|
||||
value = field.default
|
||||
|
||||
# Account for callable functions
|
||||
if callable(value):
|
||||
try:
|
||||
value = value()
|
||||
except:
|
||||
continue
|
||||
|
||||
initials[field_name] = value
|
||||
|
||||
return initials
|
||||
|
||||
def run_validation(self, data=empty):
|
||||
""" Perform serializer validation.
|
||||
In addition to running validators on the serializer fields,
|
||||
|
@ -13,6 +13,7 @@ from InvenTree.status_codes import StockStatus
|
||||
from part.models import Part, PartCategory
|
||||
from stock.models import StockItem
|
||||
from company.models import Company
|
||||
from common.models import InvenTreeSetting
|
||||
|
||||
|
||||
class PartAPITest(InvenTreeAPITestCase):
|
||||
@ -311,6 +312,59 @@ class PartAPITest(InvenTreeAPITestCase):
|
||||
|
||||
self.assertEqual(len(data['results']), n)
|
||||
|
||||
def test_default_values(self):
|
||||
"""
|
||||
Tests for 'default' values:
|
||||
|
||||
Ensure that unspecified fields revert to "default" values
|
||||
(as specified in the model field definition)
|
||||
"""
|
||||
|
||||
url = reverse('api-part-list')
|
||||
|
||||
response = self.client.post(url, {
|
||||
'name': 'all defaults',
|
||||
'description': 'my test part',
|
||||
'category': 1,
|
||||
})
|
||||
|
||||
data = response.data
|
||||
|
||||
# Check that the un-specified fields have used correct default values
|
||||
self.assertTrue(data['active'])
|
||||
self.assertFalse(data['virtual'])
|
||||
|
||||
# By default, parts are not purchaseable
|
||||
self.assertFalse(data['purchaseable'])
|
||||
|
||||
# Set the default 'purchaseable' status to True
|
||||
InvenTreeSetting.set_setting(
|
||||
'PART_PURCHASEABLE',
|
||||
True,
|
||||
self.user
|
||||
)
|
||||
|
||||
response = self.client.post(url, {
|
||||
'name': 'all defaults',
|
||||
'description': 'my test part 2',
|
||||
'category': 1,
|
||||
})
|
||||
|
||||
# Part should now be purchaseable by default
|
||||
self.assertTrue(response.data['purchaseable'])
|
||||
|
||||
# "default" values should not be used if the value is specified
|
||||
response = self.client.post(url, {
|
||||
'name': 'all defaults',
|
||||
'description': 'my test part 2',
|
||||
'category': 1,
|
||||
'active': False,
|
||||
'purchaseable': False,
|
||||
})
|
||||
|
||||
self.assertFalse(response.data['active'])
|
||||
self.assertFalse(response.data['purchaseable'])
|
||||
|
||||
|
||||
class PartDetailTests(InvenTreeAPITestCase):
|
||||
"""
|
||||
@ -391,7 +445,14 @@ class PartDetailTests(InvenTreeAPITestCase):
|
||||
|
||||
# Try to remove the part
|
||||
response = self.client.delete(url)
|
||||
|
||||
|
||||
# As the part is 'active' we cannot delete it
|
||||
self.assertEqual(response.status_code, 405)
|
||||
|
||||
# So, let's make it not active
|
||||
response = self.patch(url, {'active': False}, expected_code=200)
|
||||
|
||||
response = self.client.delete(url)
|
||||
self.assertEqual(response.status_code, 204)
|
||||
|
||||
# Part count should have reduced
|
||||
@ -542,8 +603,6 @@ class PartDetailTests(InvenTreeAPITestCase):
|
||||
# And now check that the image has been set
|
||||
p = Part.objects.get(pk=pk)
|
||||
|
||||
print("Image:", p.image.file)
|
||||
|
||||
|
||||
class PartAPIAggregationTest(InvenTreeAPITestCase):
|
||||
"""
|
||||
|
@ -354,16 +354,18 @@ class StockItemTest(StockAPITestCase):
|
||||
self.assertContains(response, 'does not exist', status_code=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# POST without quantity
|
||||
response = self.client.post(
|
||||
response = self.post(
|
||||
self.list_url,
|
||||
data={
|
||||
{
|
||||
'part': 1,
|
||||
'location': 1,
|
||||
}
|
||||
},
|
||||
expected_code=201,
|
||||
)
|
||||
|
||||
self.assertContains(response, 'This field is required', status_code=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# Item should have been created with default quantity
|
||||
self.assertEqual(response.data['quantity'], 1)
|
||||
|
||||
# POST with quantity and part and location
|
||||
response = self.client.post(
|
||||
self.list_url,
|
||||
|
Loading…
Reference in New Issue
Block a user