diff --git a/.coveragerc b/.coveragerc index d3d9b3a..9ba0ad9 100644 --- a/.coveragerc +++ b/.coveragerc @@ -3,3 +3,4 @@ omit = */site-packages/* */distutils/* tests/* + .tox/* diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e36479a..aced653 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,3 +19,5 @@ jobs: run: pip install -r requirements/test.txt - name: Run Tox run: tox -e py + - name: Upload Coverage to codecov + run: bash <(curl -s https://codecov.io/bash) diff --git a/imagekitio/file.py b/imagekitio/file.py index e7ee6ce..a18f1bb 100644 --- a/imagekitio/file.py +++ b/imagekitio/file.py @@ -1,4 +1,4 @@ -import json +from json import dumps from typing import Any, Dict from .constants.errors import ERRORS @@ -10,6 +10,10 @@ snake_to_lower_camel, ) +try: + from simplejson.errors import JSONDecodeError +except ImportError: + from json import JSONDecodeError class File(object): def __init__(self, request_obj): @@ -47,7 +51,10 @@ def upload(self, file, file_name, options) -> Dict: ) if resp.status_code > 200: - error = resp.json() + try: + error = resp.json() + except JSONDecodeError: + error = resp.text response = None else: error = None @@ -107,7 +114,7 @@ def update_file_details(self, file_id: str, options: dict): url = "{}/{}/details/".format(URL.BASE_URL.value, file_id) headers = {"Content-Type": "application/json"} headers.update(self.request.get_auth_headers()) - data = json.dumps(request_formatter(options)) + data = dumps(request_formatter(options)) resp = self.request.request(method="Patch", url=url, headers=headers, data=data) if resp.status_code > 200: error = resp.json() @@ -171,7 +178,7 @@ def purge_cache(self, file_url: str = None) -> Dict[str, Any]: headers.update(self.request.get_auth_headers()) body = {"url": file_url} resp = self.request.request( - "Post", headers=headers, url=url, data=json.dumps(body) + "Post", headers=headers, url=url, data=dumps(body) ) formatted_resp = camel_dict_to_snake_dict(resp.json()) if resp.status_code > 204: diff --git a/tests/helpers.py b/tests/helpers.py index e5d3e00..59e7ed4 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -6,6 +6,10 @@ from imagekitio.client import ImageKit from tests.dummy_data.file import AUTHENTICATION_ERR_MSG, SUCCESS_GENERIC_RESP +try: + from simplejson.errors import JSONDecodeError +except ImportError: + from json import JSONDecodeError class ClientTestCase(unittest.TestCase): @@ -41,6 +45,16 @@ def get_mocked_failed_resp(message=None, status=401): return mocked_resp +def get_mocked_failed_resp_text(): + """GET failed mocked response returned as text not json + """ + mocked_resp = Mock(spec=Response) + mocked_resp.status_code = 502 + mocked_resp.text = 'Bad Gateway' + mocked_resp.json.side_effect = JSONDecodeError("Expecting value: ", "Bad Gateway", 0) + return mocked_resp + + def get_mocked_success_resp(message: dict = None, status: int = 200): """GET success mocked response customize by parameter """ diff --git a/tests/test_files_ops.py b/tests/test_files_ops.py index 47399a2..02f0a55 100644 --- a/tests/test_files_ops.py +++ b/tests/test_files_ops.py @@ -15,6 +15,7 @@ from tests.helpers import ( ClientTestCase, get_mocked_failed_resp, + get_mocked_failed_resp_text, get_mocked_success_resp, ) from imagekitio.utils.formatter import request_formatter @@ -173,6 +174,27 @@ def test_upload_file_fails_without_file_or_file_name(self) -> None: self.assertRaises(TypeError, self.client.upload_file, file_name=self.filename) self.assertRaises(TypeError, self.client.upload_file, file=self.image) + def test_upload_file_fails_without_json_response_from_server(self) -> None: + """Test upload raises error on non json response + """ + self.client.ik_request.request = MagicMock( + return_value=get_mocked_failed_resp_text() + ) + resp = self.client.upload( + file=self.image, + file_name="fileabc", + options={ + "is_private_file": True, + "tags": ["abc"], + "response_fields": ["is_private_file", "tags"], + "custom_coordinates": "10,10,100,100", + "use_unique_file_name": True, + "folder": "abc" + } + ) + self.assertIsNotNone(resp["error"]) + self.assertIsNone(resp["response"]) + class TestListFiles(ClientTestCase): """ diff --git a/tox.ini b/tox.ini index d58b7c5..ec49579 100644 --- a/tox.ini +++ b/tox.ini @@ -5,4 +5,6 @@ skipsdist = True [testenv] passenv = * deps = -rrequirements/test.txt -commands = python -m unittest discover tests +commands = + coverage run --append -m unittest discover tests + coverage report \ No newline at end of file