From d767c3a95c9b7b6c712945815045e0e3061028a8 Mon Sep 17 00:00:00 2001 From: Chris Caron Date: Sun, 3 Dec 2017 21:48:23 -0500 Subject: [PATCH] added NotifyJSON unittests --- apprise/plugins/NotifyJSON.py | 2 +- dev-requirements.txt | 1 + test/test_plugins.py | 191 ++++++++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 test/test_plugins.py diff --git a/apprise/plugins/NotifyJSON.py b/apprise/plugins/NotifyJSON.py index 5b812c3b..655b13ce 100644 --- a/apprise/plugins/NotifyJSON.py +++ b/apprise/plugins/NotifyJSON.py @@ -119,7 +119,7 @@ class NotifyJSON(NotifyBase): # Return; we're done return False - except requests.ConnectionError as e: + except requests.RequestException as e: self.logger.warning( 'A Connection error occured sending JSON ' 'notification to %s.' % self.host) diff --git a/dev-requirements.txt b/dev-requirements.txt index 483bf77a..e32ceb99 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -2,4 +2,5 @@ pytest coverage pytest-cov pycodestyle +mock tox diff --git a/test/test_plugins.py b/test/test_plugins.py new file mode 100644 index 00000000..04a86f2d --- /dev/null +++ b/test/test_plugins.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- +# +# NotifyJSON Unit Tests +# +# Copyright (C) 2017 Chris Caron +# +# This file is part of apprise. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +from apprise import plugins +from apprise import NotifyType +from apprise import Apprise +import requests +import mock + + +VALID_URLS = ( + ################################## + # NotifyJSON + ################################## + ('json://', { + 'instance': None, + }), + ('json://localhost', { + 'instance': plugins.NotifyJSON, + }), + ('json://user:pass@localhost', { + 'instance': plugins.NotifyJSON, + }), + ('json://localhost:8080', { + 'instance': plugins.NotifyJSON, + }), + ('json://user:pass@localhost:8080', { + 'instance': plugins.NotifyJSON, + }), + ('jsons://localhost', { + 'instance': plugins.NotifyJSON, + }), + ('jsons://user:pass@localhost', { + 'instance': plugins.NotifyJSON, + }), + ('jsons://localhost:8080/path/', { + 'instance': plugins.NotifyJSON, + }), + ('jsons://user:pass@localhost:8080', { + 'instance': plugins.NotifyJSON, + }), + ('json://user:pass@localhost:8081', { + 'instance': plugins.NotifyJSON, + # force a failure + 'response': False, + 'requests_response_code': 500, + }), + ('json://user:pass@localhost:8082', { + 'instance': plugins.NotifyJSON, + # throw a bizzare code forcing us to fail to look it up + 'response': False, + 'requests_response_code': 999, + }), + ('json://user:pass@localhost:8083', { + 'instance': plugins.NotifyJSON, + # Throws a series of connection and transfer exceptions when this flag + # is set and tests that we gracfully handle them + 'test_requests_exceptions': True, + }) +) + + +@mock.patch('requests.get') +@mock.patch('requests.post') +def test_plugins(mock_post, mock_get): + """ + API: Plugins() object + + """ + + # iterate over our dictionary and test it out + for (url, meta) in VALID_URLS: + + # Our expected instance + instance = meta.get('instance', None) + + # Our expected exception + exception = meta.get('exception', None) + + # Our expected server objects + self = meta.get('self', None) + + # Our expected Query response (True, False, or exception type) + response = meta.get('response', True) + + # Allow us to force the server response code to be something other then + # the defaults + requests_response_code = meta.get( + 'requests_response_code', 200 if response else 404) + + test_requests_exceptions = meta.get( + 'test_requests_exceptions', False) + + mock_get.return_value = requests.Request() + mock_post.return_value = requests.Request() + if test_requests_exceptions is False: + # Handle our default response + mock_post.return_value.status_code = requests_response_code + mock_get.return_value.status_code = requests_response_code + mock_post.side_effect = None + mock_get.side_effect = None + + else: + # Handle exception testing; first we turn the boolean flag ito + # a list of exceptions + test_requests_exceptions = ( + requests.ConnectionError( + 0, 'requests.ConnectionError() not handled'), + requests.RequestException( + 0, 'requests.RequestException() not handled'), + requests.HTTPError( + 0, 'requests.HTTPError() not handled'), + requests.ReadTimeout( + 0, 'requests.ReadTimeout() not handled'), + requests.TooManyRedirects( + 0, 'requests.TooManyRedirects() not handled'), + ) + + try: + obj = Apprise.instantiate(url, suppress_exceptions=False) + + assert(exception is None) + + if obj is None: + # We're done + continue + + assert(isinstance(obj, instance)) + + if self: + # Iterate over our expected entries inside of our object + for key, val in self.items(): + # Test that our object has the desired key + assert(hasattr(key, obj)) + assert(getattr(key, obj) == val) + + try: + if test_requests_exceptions is False: + # check tht we're as expected + assert obj.notify( + title='test', body='body', + notify_type=NotifyType.INFO) == response + + else: + for exception in test_requests_exceptions: + mock_post.side_effect = exception + mock_get.side_effect = exception + try: + assert obj.notify( + title='test', body='body', + notify_type=NotifyType.INFO) is False + + except AssertionError: + # Don't mess with these entries + raise + + except Exception as e: + # We can't handle this exception type + assert False + + except AssertionError: + # Don't mess with these entries + raise + + except Exception as e: + # Check that we were expecting this exception to happen + assert isinstance(e, response) + + except AssertionError: + # Don't mess with these entries + raise + + except Exception as e: + # Handle our exception + assert(exception is not None) + assert(isinstance(e, exception))