/InvenTree/stock/test_api.py

https://github.com/inventree/InvenTree · Python · 327 lines · 206 code · 83 blank · 38 comment · 1 complexity · 3de2eeab34164a59d5c0e524417344af MD5 · raw file

  1. from rest_framework.test import APITestCase
  2. from rest_framework import status
  3. from django.urls import reverse
  4. from django.contrib.auth import get_user_model
  5. from InvenTree.helpers import addUserPermissions
  6. from .models import StockLocation
  7. class StockAPITestCase(APITestCase):
  8. fixtures = [
  9. 'category',
  10. 'part',
  11. 'company',
  12. 'location',
  13. 'supplier_part',
  14. 'stock',
  15. 'stock_tests',
  16. ]
  17. def setUp(self):
  18. # Create a user for auth
  19. User = get_user_model()
  20. self.user = User.objects.create_user('testuser', 'test@testing.com', 'password')
  21. # Add the necessary permissions to the user
  22. perms = [
  23. 'view_stockitemtestresult',
  24. 'change_stockitemtestresult',
  25. 'add_stockitemtestresult',
  26. 'add_stocklocation',
  27. 'change_stocklocation',
  28. 'add_stockitem',
  29. 'change_stockitem',
  30. ]
  31. addUserPermissions(self.user, perms)
  32. self.client.login(username='testuser', password='password')
  33. def doPost(self, url, data={}):
  34. response = self.client.post(url, data=data, format='json')
  35. return response
  36. class StockLocationTest(StockAPITestCase):
  37. """
  38. Series of API tests for the StockLocation API
  39. """
  40. list_url = reverse('api-location-list')
  41. def setUp(self):
  42. super().setUp()
  43. # Add some stock locations
  44. StockLocation.objects.create(name='top', description='top category')
  45. def test_list(self):
  46. # Check that we can request the StockLocation list
  47. response = self.client.get(self.list_url, format='json')
  48. self.assertEqual(response.status_code, status.HTTP_200_OK)
  49. self.assertGreaterEqual(len(response.data), 1)
  50. def test_add(self):
  51. # Check that we can add a new StockLocation
  52. data = {
  53. 'parent': 1,
  54. 'name': 'Location',
  55. 'description': 'Another location for stock'
  56. }
  57. response = self.client.post(self.list_url, data, format='json')
  58. self.assertEqual(response.status_code, status.HTTP_201_CREATED)
  59. class StockItemTest(StockAPITestCase):
  60. """
  61. Series of API tests for the StockItem API
  62. """
  63. list_url = reverse('api-stock-list')
  64. def detail_url(self, pk):
  65. return reverse('api-stock-detail', kwargs={'pk': pk})
  66. def setUp(self):
  67. super().setUp()
  68. # Create some stock locations
  69. top = StockLocation.objects.create(name='A', description='top')
  70. StockLocation.objects.create(name='B', description='location b', parent=top)
  71. StockLocation.objects.create(name='C', description='location c', parent=top)
  72. def test_get_stock_list(self):
  73. response = self.client.get(self.list_url, format='json')
  74. self.assertEqual(response.status_code, status.HTTP_200_OK)
  75. def test_stock_item_create(self):
  76. """
  77. Test creation of a StockItem via the API
  78. """
  79. # POST with an empty part reference
  80. response = self.client.post(
  81. self.list_url,
  82. data={
  83. 'quantity': 10,
  84. 'location': 1
  85. }
  86. )
  87. self.assertContains(response, 'This field is required', status_code=status.HTTP_400_BAD_REQUEST)
  88. # POST with an invalid part reference
  89. response = self.client.post(
  90. self.list_url,
  91. data={
  92. 'quantity': 10,
  93. 'location': 1,
  94. 'part': 10000000,
  95. }
  96. )
  97. self.assertContains(response, 'does not exist', status_code=status.HTTP_400_BAD_REQUEST)
  98. # POST without quantity
  99. response = self.client.post(
  100. self.list_url,
  101. data={
  102. 'part': 1,
  103. 'location': 1,
  104. }
  105. )
  106. self.assertContains(response, 'This field is required', status_code=status.HTTP_400_BAD_REQUEST)
  107. # POST with quantity and part and location
  108. response = self.client.post(
  109. self.list_url,
  110. data={
  111. 'part': 1,
  112. 'location': 1,
  113. 'quantity': 10,
  114. }
  115. )
  116. self.assertEqual(response.status_code, status.HTTP_201_CREATED)
  117. class StocktakeTest(StockAPITestCase):
  118. """
  119. Series of tests for the Stocktake API
  120. """
  121. def test_action(self):
  122. """
  123. Test each stocktake action endpoint,
  124. for validation
  125. """
  126. for endpoint in ['api-stock-count', 'api-stock-add', 'api-stock-remove']:
  127. url = reverse(endpoint)
  128. data = {}
  129. # POST with a valid action
  130. response = self.doPost(url, data)
  131. self.assertContains(response, "must contain list", status_code=status.HTTP_400_BAD_REQUEST)
  132. data['items'] = [{
  133. 'no': 'aa'
  134. }]
  135. # POST without a PK
  136. response = self.doPost(url, data)
  137. self.assertContains(response, 'must contain a valid pk', status_code=status.HTTP_400_BAD_REQUEST)
  138. # POST with a PK but no quantity
  139. data['items'] = [{
  140. 'pk': 10
  141. }]
  142. response = self.doPost(url, data)
  143. self.assertContains(response, 'must contain a valid pk', status_code=status.HTTP_400_BAD_REQUEST)
  144. data['items'] = [{
  145. 'pk': 1234
  146. }]
  147. response = self.doPost(url, data)
  148. self.assertContains(response, 'must contain a valid quantity', status_code=status.HTTP_400_BAD_REQUEST)
  149. data['items'] = [{
  150. 'pk': 1234,
  151. 'quantity': '10x0d'
  152. }]
  153. response = self.doPost(url, data)
  154. self.assertContains(response, 'must contain a valid quantity', status_code=status.HTTP_400_BAD_REQUEST)
  155. data['items'] = [{
  156. 'pk': 1234,
  157. 'quantity': "-1.234"
  158. }]
  159. response = self.doPost(url, data)
  160. self.assertContains(response, 'must not be less than zero', status_code=status.HTTP_400_BAD_REQUEST)
  161. # Test with a single item
  162. data = {
  163. 'item': {
  164. 'pk': 1234,
  165. 'quantity': '10',
  166. }
  167. }
  168. response = self.doPost(url, data)
  169. self.assertEqual(response.status_code, status.HTTP_200_OK)
  170. def test_transfer(self):
  171. """
  172. Test stock transfers
  173. """
  174. data = {
  175. 'item': {
  176. 'pk': 1234,
  177. 'quantity': 10,
  178. },
  179. 'location': 1,
  180. 'notes': "Moving to a new location"
  181. }
  182. url = reverse('api-stock-transfer')
  183. response = self.doPost(url, data)
  184. self.assertContains(response, "Moved 1 parts to", status_code=status.HTTP_200_OK)
  185. # Now try one which will fail due to a bad location
  186. data['location'] = 'not a location'
  187. response = self.doPost(url, data)
  188. self.assertContains(response, 'Valid location must be specified', status_code=status.HTTP_400_BAD_REQUEST)
  189. class StockTestResultTest(StockAPITestCase):
  190. def get_url(self):
  191. return reverse('api-stock-test-result-list')
  192. def test_list(self):
  193. url = self.get_url()
  194. response = self.client.get(url)
  195. self.assertEqual(response.status_code, status.HTTP_200_OK)
  196. self.assertGreaterEqual(len(response.data), 4)
  197. response = self.client.get(url, data={'stock_item': 105})
  198. self.assertEqual(response.status_code, status.HTTP_200_OK)
  199. self.assertGreaterEqual(len(response.data), 4)
  200. def test_post_fail(self):
  201. # Attempt to post a new test result without specifying required data
  202. url = self.get_url()
  203. response = self.client.post(
  204. url,
  205. data={
  206. 'test': 'A test',
  207. 'result': True,
  208. },
  209. format='json'
  210. )
  211. self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
  212. # This one should pass!
  213. response = self.client.post(
  214. url,
  215. data={
  216. 'test': 'A test',
  217. 'stock_item': 105,
  218. 'result': True,
  219. },
  220. format='json'
  221. )
  222. self.assertEqual(response.status_code, status.HTTP_201_CREATED)
  223. def test_post(self):
  224. # Test creation of a new test result
  225. url = self.get_url()
  226. response = self.client.get(url)
  227. n = len(response.data)
  228. data = {
  229. 'stock_item': 105,
  230. 'test': 'Checked Steam Valve',
  231. 'result': False,
  232. 'value': '150kPa',
  233. 'notes': 'I guess there was just too much pressure?',
  234. }
  235. response = self.client.post(url, data, format='json')
  236. self.assertEqual(response.status_code, status.HTTP_201_CREATED)
  237. response = self.client.get(url)
  238. self.assertEqual(len(response.data), n + 1)
  239. # And read out again
  240. response = self.client.get(url, data={'test': 'Checked Steam Valve'})
  241. self.assertEqual(len(response.data), 1)
  242. test = response.data[0]
  243. self.assertEqual(test['value'], '150kPa')
  244. self.assertEqual(test['user'], self.user.pk)