diff --git a/InvenTree/plugin/base/integration/mixins.py b/InvenTree/plugin/base/integration/mixins.py index 7a14a9a890..6a18216209 100644 --- a/InvenTree/plugin/base/integration/mixins.py +++ b/InvenTree/plugin/base/integration/mixins.py @@ -1,6 +1,6 @@ """Plugin mixin classes.""" -import json +import json as json_pkg import logging from django.db.utils import OperationalError, ProgrammingError @@ -413,7 +413,7 @@ class APICallMixin: groups.append(f'{key}={",".join([str(a) for a in val])}') return f'?{"&".join(groups)}' - def api_call(self, endpoint: str, method: str = 'GET', url_args: dict = None, data=None, headers: dict = None, simple_response: bool = True, endpoint_is_url: bool = False): + def api_call(self, endpoint: str, method: str = 'GET', url_args: dict = None, data=None, json=None, headers: dict = None, simple_response: bool = True, endpoint_is_url: bool = False): """Do an API call. Simplest call example: @@ -426,7 +426,8 @@ class APICallMixin: endpoint (str): Path to current endpoint. Either the endpoint or the full or if the flag is set method (str, optional): HTTP method that should be uses - capitalized. Defaults to 'GET'. url_args (dict, optional): arguments that should be appended to the url. Defaults to None. - data (Any, optional): Data that should be transmitted in the body - must be JSON serializable. Defaults to None. + data (Any, optional): Data that should be transmitted in the body - url-encoded. Defaults to None. + json (Any, optional): Data that should be transmitted in the body - must be JSON serializable. Defaults to None. headers (dict, optional): Headers that should be used for the request. Defaults to self.api_headers. simple_response (bool, optional): Return the response as JSON. Defaults to True. endpoint_is_url (bool, optional): The provided endpoint is the full url - do not use self.api_url as base. Defaults to False. @@ -455,8 +456,14 @@ class APICallMixin: 'headers': headers, } + if data and json: + raise ValueError('You can either pass `data` or `json` to this function.') + + if json: + kwargs['data'] = json_pkg.dumps(json) + if data: - kwargs['data'] = json.dumps(data) + kwargs['data'] = data # run command response = requests.request(method, **kwargs) diff --git a/InvenTree/plugin/base/integration/test_mixins.py b/InvenTree/plugin/base/integration/test_mixins.py index 3f95d56694..d48b0ddc30 100644 --- a/InvenTree/plugin/base/integration/test_mixins.py +++ b/InvenTree/plugin/base/integration/test_mixins.py @@ -258,7 +258,7 @@ class APICallMixinTest(BaseMixinDefinition, TestCase): # api_call with post and data result = self.mixin.api_call( 'https://reqres.in/api/users/', - data={"name": "morpheus", "job": "leader"}, + json={"name": "morpheus", "job": "leader"}, method='POST', endpoint_is_url=True, ) @@ -280,6 +280,25 @@ class APICallMixinTest(BaseMixinDefinition, TestCase): with self.assertRaises(MixinNotImplementedError): self.mixin_wrong2.has_api_call() + # Too many data arguments + with self.assertRaises(ValueError): + self.mixin.api_call( + 'https://reqres.in/api/users/', + json={"a": 1, }, data={"a": 1}, + ) + + # Sending a request with a wrong data format should result in 40 + result = self.mixin.api_call( + 'https://reqres.in/api/users/', + data={"name": "morpheus", "job": "leader"}, + method='POST', + endpoint_is_url=True, + simple_response=False + ) + + self.assertEqual(result.status_code, 400) + self.assertIn('Bad Request', str(result.content)) + class PanelMixinTests(InvenTreeTestCase): """Test that the PanelMixin plugin operates correctly."""