From 241f9783ad00fc9b3aec07e2d41a9a6724104495 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 27 Apr 2019 14:50:49 +1000 Subject: [PATCH 1/4] Added further testing for Part/Bom API --- InvenTree/part/api.py | 2 +- InvenTree/part/test_api.py | 185 +++++++++++++++++++++++++++---------- 2 files changed, 137 insertions(+), 50 deletions(-) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index e600a303bb..9b5aef436a 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -239,7 +239,7 @@ part_api_urls = [ bom_api_urls = [ # BOM Item Detail - url('^(?P\d+)/?', BomDetail.as_view(), name='api-bom-detail'), + url('^(?P\d+)/', BomDetail.as_view(), name='api-bom-detail'), # Catch-all url(r'^.*$', BomList.as_view(), name='api-bom-list'), diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index 6546ea7109..9a0a49447b 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -4,55 +4,15 @@ from django.urls import reverse from django.contrib.auth import get_user_model from .models import Part, PartCategory - - -class BomAPITest(APITestCase): - - def setUp(self): - # Create a user for auth - User = get_user_model() - User.objects.create_user('testuser', 'test@testing.com', 'password') - - self.client.login(username='testuser', password='password') - - def test_category_list_empty(self): - # Check that we can retrieve an (empty) category list - url = reverse('api-part-category-list') - response = self.client.get(url, format='json') - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(len(response.data), 0) - - def test_add_categories(self): - # Check that we can add categories - data = { - 'name': 'Animals', - 'description': 'All animals go here' - } - - url = reverse('api-part-category-list') - response = self.client.post(url, data=data, format='json') - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - self.assertEqual(response.data['pk'], 1) - - # Add some sub-categories to the top-level 'Animals' category - for animal in ['cat', 'dog', 'zebra']: - data = { - 'name': animal, - 'description': 'A sort of animal', - 'parent': 1, - } - response = self.client.post(url, data=data, format='json') - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - self.assertEqual(response.data['parent'], 1) - self.assertEqual(response.data['name'], animal) - self.assertEqual(response.data['pathstring'], 'Animals/' + animal) - - # There should be now 4 categories - response = self.client.get(url, format='json') - self.assertEqual(len(response.data), 4) +from .models import BomItem class PartAPITest(APITestCase): + """ + Series of tests for the Part DRF API + - Tests for Part API + - Tests for PartCategory API + """ def setUp(self): # Create a user for auth @@ -75,6 +35,59 @@ class PartAPITest(APITestCase): Part.objects.create(name='C.c1', description='c1 in C', category=C) Part.objects.create(name='C.c2', description='c2 in C', category=C) + def test_get_categories(self): + # Test that we can retrieve list of part categories + url = reverse('api-part-category-list') + response = self.client.get(url, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data), 4) + + def test_add_categories(self): + # Check that we can add categories + data = { + 'name': 'Animals', + 'description': 'All animals go here' + } + + url = reverse('api-part-category-list') + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(response.data['pk'], 5) + + # Add some sub-categories to the top-level 'Animals' category + for animal in ['cat', 'dog', 'zebra']: + data = { + 'name': animal, + 'description': 'A sort of animal', + 'parent': 5, + } + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(response.data['parent'], 5) + self.assertEqual(response.data['name'], animal) + self.assertEqual(response.data['pathstring'], 'Animals/' + animal) + + # There should be now 8 categories + response = self.client.get(url, format='json') + self.assertEqual(len(response.data), 8) + + def test_cat_detail(self): + url = reverse('api-part-category-detail', kwargs={'pk': 4}) + response = self.client.get(url, format='json') + + # Test that we have retrieved the category + self.assertEqual(response.data['description'], 'Cat C') + self.assertEqual(response.data['parent'], 1) + + # Change some data and post it back + data = response.data + data['name'] = 'Changing category' + data['parent'] = None + data['description'] = 'Changing the description' + response = self.client.patch(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['description'], 'Changing the description') + def test_get_all_parts(self): url = reverse('api-part-list') response = self.client.get(url, format='json') @@ -84,7 +97,7 @@ class PartAPITest(APITestCase): def test_get_parts_by_cat(self): url = reverse('api-part-list') data = {'category': 4} - response = self.client.get(url, data=data, format='json') + response = self.client.get(url, data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) # There should only be 2 objects in category C @@ -100,7 +113,7 @@ class PartAPITest(APITestCase): url = reverse('api-part-list') data = {'category': 1} - response = self.client.get(url, data=data, format='json') + response = self.client.get(url, data, format='json') # There should be 1 part in this category self.assertEqual(len(response.data), 1) @@ -108,8 +121,82 @@ class PartAPITest(APITestCase): data['include_child_categories'] = 1 # Now request to include child categories - response = self.client.get(url, data=data, format='json') + response = self.client.get(url, data, format='json') # Now there should be 5 total parts self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data), 5) + + +class BomAPITest(APITestCase): + + def setUp(self): + # Create a user for auth + User = get_user_model() + User.objects.create_user('testuser', 'test@testing.com', 'password') + + self.client.login(username='testuser', password='password') + + # Create some parts + m1 = Part.objects.create(name='A thing', description='Made from other parts', buildable=True) + m2 = Part.objects.create(name='Another thing', description='Made from other parts', buildable=True) + + s1 = Part.objects.create(name='Sub 1', description='Required to make a thing') + s2 = Part.objects.create(name='Sub 2', description='Required to make a thing') + s3 = Part.objects.create(name='Sub 3', description='Required to make a thing') + + # Link BOM items together + BomItem.objects.create(part=m1, sub_part=s1, quantity=10) + BomItem.objects.create(part=m1, sub_part=s2, quantity=100) + BomItem.objects.create(part=m1, sub_part=s3, quantity=40) + + BomItem.objects.create(part=m2, sub_part=s3, quantity=7) + + def test_get_bom_list(self): + # There should be 4 BomItem objects in the database + url = reverse('api-bom-list') + response = self.client.get(url, format='json') + self.assertEqual(len(response.data), 4) + + def test_get_bom_detail(self): + # Get the detail for a single BomItem + url = reverse('api-bom-detail', kwargs={'pk': 3}) + response = self.client.get(url, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['quantity'], 40) + + # Increase the quantity + data = response.data + data['quantity'] = 57 + data['note'] = 'Added a note' + + response = self.client.patch(url, data, format='json') + + # Check that the quantity was increased and a note added + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['quantity'], 57) + self.assertEqual(response.data['note'], 'Added a note') + + def test_add_bom_item(self): + url = reverse('api-bom-list') + + data = { + 'part': 2, + 'sub_part': 4, + 'quantity': 777, + } + + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + # Now try to create a BomItem which points to a non-buildable part (should fail) + data['part'] = 3 + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + # Now try to create a BomItem which references itself + data['part'] = 2 + data['sub_part'] = 2 + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertIn('cannot be added to its own', str(response.data['sub_part'][0])) From 1fbea088dc26832871e98e81ca82e534bbe7c237 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 27 Apr 2019 15:02:20 +1000 Subject: [PATCH 2/4] Added API test for Company app --- InvenTree/company/test_api.py | 61 +++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 InvenTree/company/test_api.py diff --git a/InvenTree/company/test_api.py b/InvenTree/company/test_api.py new file mode 100644 index 0000000000..f81e1607fb --- /dev/null +++ b/InvenTree/company/test_api.py @@ -0,0 +1,61 @@ +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 .models import Company + + +class CompanyTest(APITestCase): + """ + Series of tests for the Company DRF API + """ + + def setUp(self): + # Create a user for auth + User = get_user_model() + User.objects.create_user('testuser', 'test@testing.com', 'password') + self.client.login(username='testuser', password='password') + + Company.objects.create(name='ACME', description='Supplier', is_customer=False, is_supplier=True) + Company.objects.create(name='Drippy Cup Co.', description='Customer', is_customer=True, is_supplier=False) + Company.objects.create(name='Sippy Cup Emporium', description='Another supplier') + + def test_company_list(self): + url = reverse('api-company-list') + + # There should be two companies + response = self.client.get(url, format='json') + self.assertEqual(len(response.data), 3) + + data = {'is_customer': True} + + # There should only be one customer + response = self.client.get(url, data, format='json') + self.assertEqual(len(response.data), 1) + + data = {'is_supplier': True} + + # There should be two suppliers + response = self.client.get(url, data, format='json') + self.assertEqual(len(response.data), 2) + + def test_company_detail(self): + url = reverse('api-company-detail', kwargs={'pk': 1}) + response = self.client.get(url, format='json') + + self.assertEqual(response.data['name'], 'ACME') + + # Change the name of the company + data = response.data + data['name'] = 'ACMOO' + response = self.client.patch(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['name'], 'ACMOO') + + def test_company_search(self): + # Test search functionality in company list + url = reverse('api-company-list') + data = {'search': 'cup'} + response = self.client.get(url, data, format='json') + self.assertEqual(len(response.data), 2) From e7685951e1d271b07df0e4a0681a2404806f4028 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 27 Apr 2019 15:24:30 +1000 Subject: [PATCH 3/4] Add (simple) test cases for Stock API - Still a lot of work to do here --- InvenTree/stock/test_api.py | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 InvenTree/stock/test_api.py diff --git a/InvenTree/stock/test_api.py b/InvenTree/stock/test_api.py new file mode 100644 index 0000000000..c526116e91 --- /dev/null +++ b/InvenTree/stock/test_api.py @@ -0,0 +1,65 @@ +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 .models import StockLocation, StockItem + + +class StockLocationTest(APITestCase): + """ + Series of API tests for the StockLocation API + """ + list_url = reverse('api-location-list') + + def setUp(self): + # Create a user for auth + User = get_user_model() + User.objects.create_user('testuser', 'test@testing.com', 'password') + self.client.login(username='testuser', password='password') + + # Add some stock locations + StockLocation.objects.create(name='top', description='top category') + + def test_list(self): + # Check that we can request the StockLocation list + response = self.client.get(self.list_url, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertGreaterEqual(len(response.data), 1) + + def test_add(self): + # Check that we can add a new StockLocation + data = { + 'parent': 1, + 'name': 'Location', + 'description': 'Another location for stock' + } + response = self.client.post(self.list_url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + +class StockItemTest(APITestCase): + """ + Series of API tests for the StockItem API + """ + + list_url = reverse('api-stock-list') + + def detail_url(self, pk): + return revere('api-stock-detail', kwargs={'pk': pk}) + + def setUp(self): + # Create a user for auth + User = get_user_model() + User.objects.create_user('testuser', 'test@testing.com', 'password') + self.client.login(username='testuser', password='password') + + # Create some stock locations + top = StockLocation.objects.create(name='A', description='top') + + 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) From 0484e6283669bd5b7dcb4c96120cfef50260446c Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 27 Apr 2019 15:25:40 +1000 Subject: [PATCH 4/4] PEP fixes --- InvenTree/company/test_api.py | 2 +- InvenTree/stock/test_api.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/InvenTree/company/test_api.py b/InvenTree/company/test_api.py index f81e1607fb..bf4cc6643e 100644 --- a/InvenTree/company/test_api.py +++ b/InvenTree/company/test_api.py @@ -7,7 +7,7 @@ from .models import Company class CompanyTest(APITestCase): - """ + """ Series of tests for the Company DRF API """ diff --git a/InvenTree/stock/test_api.py b/InvenTree/stock/test_api.py index c526116e91..27207020b4 100644 --- a/InvenTree/stock/test_api.py +++ b/InvenTree/stock/test_api.py @@ -3,11 +3,11 @@ from rest_framework import status from django.urls import reverse from django.contrib.auth import get_user_model -from .models import StockLocation, StockItem +from .models import StockLocation class StockLocationTest(APITestCase): - """ + """ Series of API tests for the StockLocation API """ list_url = reverse('api-location-list') @@ -46,7 +46,7 @@ class StockItemTest(APITestCase): list_url = reverse('api-stock-list') def detail_url(self, pk): - return revere('api-stock-detail', kwargs={'pk': pk}) + return reverse('api-stock-detail', kwargs={'pk': pk}) def setUp(self): # Create a user for auth