mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-26 10:57:40 +00:00 
			
		
		
		
	Improve unit testing for StockItem API
This commit is contained in:
		| @@ -28,7 +28,7 @@ class BuildSerializer(InvenTreeModelSerializer): | ||||
|  | ||||
|     quantity = serializers.FloatField() | ||||
|  | ||||
|     overdue = serializers.BooleanField() | ||||
|     overdue = serializers.BooleanField(required=False, read_only=True) | ||||
|  | ||||
|     @staticmethod | ||||
|     def annotate_queryset(queryset): | ||||
|   | ||||
| @@ -181,7 +181,7 @@ class SalesOrderSerializer(InvenTreeModelSerializer): | ||||
|  | ||||
|     status_text = serializers.CharField(source='get_status_display', read_only=True) | ||||
|  | ||||
|     overdue = serializers.BooleanField() | ||||
|     overdue = serializers.BooleanField(required=False, read_only=True) | ||||
|  | ||||
|     class Meta: | ||||
|         model = SalesOrder | ||||
|   | ||||
| @@ -134,6 +134,7 @@ | ||||
|   fields: | ||||
|     name: 'Red chair' | ||||
|     variant_of: 10000 | ||||
|     IPN: "R.CH" | ||||
|     trackable: true | ||||
|     category: 7 | ||||
|     tree_id: 1 | ||||
|   | ||||
| @@ -69,7 +69,7 @@ | ||||
|     part: 25 | ||||
|     batch: 'ABCDE' | ||||
|     location: 7 | ||||
|     quantity: 3 | ||||
|     quantity: 0 | ||||
|     level: 0 | ||||
|     tree_id: 0 | ||||
|     lft: 0 | ||||
| @@ -220,6 +220,7 @@ | ||||
|     tree_id: 0 | ||||
|     lft: 0 | ||||
|     rght: 0 | ||||
|     expiry_date: "1990-10-10" | ||||
|  | ||||
| - model: stock.stockitem | ||||
|   pk: 521 | ||||
| @@ -232,6 +233,7 @@ | ||||
|     tree_id: 0 | ||||
|     lft: 0 | ||||
|     rght: 0 | ||||
|     status: 60 | ||||
|  | ||||
| - model: stock.stockitem | ||||
|   pk: 522 | ||||
| @@ -244,3 +246,5 @@ | ||||
|     tree_id: 0 | ||||
|     lft: 0 | ||||
|     rght: 0 | ||||
|     expiry_date: "1990-10-10" | ||||
|     status: 70 | ||||
| @@ -135,7 +135,7 @@ class StockItemSerializer(InvenTreeModelSerializer): | ||||
|      | ||||
|     allocated = serializers.FloatField(source='allocation_count', required=False) | ||||
|  | ||||
|     expired = serializers.BooleanField() | ||||
|     expired = serializers.BooleanField(required=False, read_only=True) | ||||
|  | ||||
|     serial = serializers.CharField(required=False) | ||||
|  | ||||
|   | ||||
| @@ -1,11 +1,21 @@ | ||||
| """ | ||||
| Unit testing for the Stock API | ||||
| """ | ||||
|  | ||||
| # -*- coding: utf-8 -*- | ||||
| from __future__ import unicode_literals | ||||
|  | ||||
| from datetime import datetime, timedelta | ||||
|  | ||||
| from rest_framework.test import APITestCase | ||||
| from rest_framework import status | ||||
| from django.urls import reverse | ||||
| from django.contrib.auth import get_user_model | ||||
|  | ||||
| from InvenTree.helpers import addUserPermissions | ||||
| from InvenTree.status_codes import StockStatus | ||||
|  | ||||
| from .models import StockLocation | ||||
| from .models import StockItem, StockLocation | ||||
|  | ||||
|  | ||||
| class StockAPITestCase(APITestCase): | ||||
| @@ -76,6 +86,170 @@ class StockLocationTest(StockAPITestCase): | ||||
|         self.assertEqual(response.status_code, status.HTTP_201_CREATED) | ||||
|  | ||||
|  | ||||
| class StockItemListTest(StockAPITestCase): | ||||
|     """ | ||||
|     Tests for the StockItem API LIST endpoint | ||||
|     """ | ||||
|  | ||||
|     list_url = reverse('api-stock-list') | ||||
|  | ||||
|     def get_stock(self, **kwargs): | ||||
|         """ | ||||
|         Filter stock and return JSON object | ||||
|         """ | ||||
|  | ||||
|         response = self.client.get(self.list_url, format='json', data=kwargs) | ||||
|  | ||||
|         self.assertEqual(response.status_code, status.HTTP_200_OK) | ||||
|  | ||||
|         # Return JSON-ified data | ||||
|         return response.data | ||||
|  | ||||
|     def test_get_stock_list(self): | ||||
|         """ | ||||
|         List *all* StockItem objects. | ||||
|         """ | ||||
|  | ||||
|         response = self.get_stock() | ||||
|  | ||||
|         self.assertEqual(len(response), 19) | ||||
|  | ||||
|     def test_filter_by_part(self): | ||||
|         """ | ||||
|         Filter StockItem by Part reference | ||||
|         """ | ||||
|  | ||||
|         response = self.get_stock(part=25) | ||||
|          | ||||
|         self.assertEqual(len(response), 7) | ||||
|  | ||||
|         response = self.get_stock(part=10004) | ||||
|  | ||||
|         self.assertEqual(len(response), 12) | ||||
|  | ||||
|     def test_filter_by_IPN(self): | ||||
|         """ | ||||
|         Filter StockItem by IPN reference | ||||
|         """ | ||||
|  | ||||
|         response = self.get_stock(IPN="R.CH") | ||||
|         self.assertEqual(len(response), 3) | ||||
|  | ||||
|     def test_filter_by_location(self): | ||||
|         """ | ||||
|         Filter StockItem by StockLocation reference | ||||
|         """ | ||||
|  | ||||
|         response = self.get_stock(location=5) | ||||
|         self.assertEqual(len(response), 1) | ||||
|  | ||||
|         response = self.get_stock(location=1, cascade=0) | ||||
|         self.assertEqual(len(response), 0) | ||||
|  | ||||
|         response = self.get_stock(location=1, cascade=1) | ||||
|         self.assertEqual(len(response), 2) | ||||
|  | ||||
|         response = self.get_stock(location=7) | ||||
|         self.assertEqual(len(response), 16) | ||||
|  | ||||
|     def test_filter_by_depleted(self): | ||||
|         """ | ||||
|         Filter StockItem by depleted status | ||||
|         """ | ||||
|  | ||||
|         response = self.get_stock(depleted=1) | ||||
|         self.assertEqual(len(response), 1) | ||||
|  | ||||
|         response = self.get_stock(depleted=0) | ||||
|         self.assertEqual(len(response), 18) | ||||
|  | ||||
|     def test_filter_by_in_stock(self): | ||||
|         """ | ||||
|         Filter StockItem by 'in stock' status | ||||
|         """ | ||||
|  | ||||
|         response = self.get_stock(in_stock=1) | ||||
|         self.assertEqual(len(response), 16) | ||||
|  | ||||
|         response = self.get_stock(in_stock=0) | ||||
|         self.assertEqual(len(response), 3) | ||||
|  | ||||
|     def test_filter_by_status(self): | ||||
|         """ | ||||
|         Filter StockItem by 'status' field | ||||
|         """ | ||||
|  | ||||
|         codes = { | ||||
|             StockStatus.OK: 17, | ||||
|             StockStatus.DESTROYED: 1, | ||||
|             StockStatus.LOST: 1, | ||||
|             StockStatus.DAMAGED: 0, | ||||
|             StockStatus.REJECTED: 0, | ||||
|         } | ||||
|  | ||||
|         for code in codes.keys(): | ||||
|             num = codes[code] | ||||
|  | ||||
|             response = self.get_stock(status=code) | ||||
|             self.assertEqual(len(response), num) | ||||
|  | ||||
|     def test_filter_by_batch(self): | ||||
|         """ | ||||
|         Filter StockItem by batch code | ||||
|         """ | ||||
|  | ||||
|         response = self.get_stock(batch='B123') | ||||
|         self.assertEqual(len(response), 1) | ||||
|  | ||||
|     def test_filter_by_serialized(self): | ||||
|         """ | ||||
|         Filter StockItem by serialized status | ||||
|         """ | ||||
|  | ||||
|         response = self.get_stock(serialized=1) | ||||
|         self.assertEqual(len(response), 12) | ||||
|  | ||||
|         for item in response: | ||||
|             self.assertIsNotNone(item['serial']) | ||||
|  | ||||
|         response = self.get_stock(serialized=0) | ||||
|         self.assertEqual(len(response), 7) | ||||
|  | ||||
|         for item in response: | ||||
|             self.assertIsNone(item['serial']) | ||||
|  | ||||
|     def test_filter_by_expired(self): | ||||
|         """ | ||||
|         Filter StockItem by expiry status | ||||
|         """ | ||||
|  | ||||
|         response = self.get_stock(expired=1) | ||||
|         self.assertEqual(len(response), 1) | ||||
|  | ||||
|         for item in response: | ||||
|             self.assertTrue(item['expired']) | ||||
|  | ||||
|         response = self.get_stock(expired=0) | ||||
|         self.assertEqual(len(response), 18) | ||||
|  | ||||
|         for item in response: | ||||
|             self.assertFalse(item['expired']) | ||||
|  | ||||
|         # Mark some other stock items as expired | ||||
|         today = datetime.now().date() | ||||
|  | ||||
|         for pk in [510, 511, 512]: | ||||
|             item = StockItem.objects.get(pk=pk) | ||||
|             item.expiry_date = today - timedelta(days=pk) | ||||
|             item.save() | ||||
|  | ||||
|         response = self.get_stock(expired=1) | ||||
|         self.assertEqual(len(response), 4) | ||||
|  | ||||
|         response = self.get_stock(expired=0) | ||||
|         self.assertEqual(len(response), 15) | ||||
|  | ||||
|  | ||||
| class StockItemTest(StockAPITestCase): | ||||
|     """ | ||||
|     Series of API tests for the StockItem API | ||||
| @@ -94,10 +268,6 @@ class StockItemTest(StockAPITestCase): | ||||
|         StockLocation.objects.create(name='B', description='location b', parent=top) | ||||
|         StockLocation.objects.create(name='C', description='location c', parent=top) | ||||
|  | ||||
|     def test_get_stock_list(self): | ||||
|         response = self.client.get(self.list_url, format='json') | ||||
|         self.assertEqual(response.status_code, status.HTTP_200_OK) | ||||
|  | ||||
|     def test_create_default_location(self): | ||||
|         """ | ||||
|         Test the default location functionality, | ||||
|   | ||||
| @@ -177,8 +177,10 @@ class StockTest(TestCase): | ||||
|         # There should be 9000 screws in stock | ||||
|         self.assertEqual(part.total_stock, 9000) | ||||
|  | ||||
|         # There should be 18 widgets in stock | ||||
|         self.assertEqual(StockItem.objects.filter(part=25).aggregate(Sum('quantity'))['quantity__sum'], 19) | ||||
|         # There should be 16 widgets "in stock" | ||||
|         self.assertEqual( | ||||
|             StockItem.objects.filter(part=25).aggregate(Sum('quantity'))['quantity__sum'], 16 | ||||
|         ) | ||||
|  | ||||
|     def test_delete_location(self): | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user