def test_smtplib_send_okay(mock_smtplib): """ API: Test a successfully sent email """ # Disable Throttling to speed testing plugins.NotifyBase.NotifyBase.request_rate_per_sec = 0 # Defaults to HTML obj = Apprise.instantiate('mailto://*****:*****@gmail.com', suppress_exceptions=False) assert (isinstance(obj, plugins.NotifyEmail)) # Support an email simulation where we can correctly quit mock_smtplib.starttls.return_value = True mock_smtplib.login.return_value = True mock_smtplib.sendmail.return_value = True mock_smtplib.quit.return_value = True assert (obj.notify(body='body', title='test', notify_type=NotifyType.INFO) is True) # Set Text obj = Apprise.instantiate('mailto://*****:*****@gmail.com?format=text', suppress_exceptions=False) assert (isinstance(obj, plugins.NotifyEmail)) assert (obj.notify(body='body', title='test', notify_type=NotifyType.INFO) is True)
def test_twist_plugin_init(): """ API: NotifyTwist init() """ try: plugins.NotifyTwist(email='invalid', targets=None) assert False except TypeError: # Invalid email address assert True try: plugins.NotifyTwist(email='user@domain', targets=None) assert False except TypeError: # No password was specified assert True # Simple object initialization result = plugins.NotifyTwist(password='******', email='*****@*****.**', targets=None) assert result.user == 'user' assert result.host == 'domain.com' assert result.password == 'abc123' # Channel Instantiation by name obj = Apprise.instantiate('twist://*****:*****@example.com/#Channel') assert isinstance(obj, plugins.NotifyTwist) # Channel Instantiation by id (faster if you know the translation) obj = Apprise.instantiate('twist://*****:*****@example.com/12345') assert isinstance(obj, plugins.NotifyTwist) # Invalid Channel - (max characters is 64), the below drops it obj = Apprise.instantiate('twist://*****:*****@example.com/{}'.format( 'a' * 65)) assert isinstance(obj, plugins.NotifyTwist) # No User detect result = plugins.NotifyTwist.parse_url('twist://example.com') assert result is None # test usage of to= result = plugins.NotifyTwist.parse_url( 'twist://*****:*****@example.com?to=#channel') assert isinstance(result, dict) assert 'user' in result assert result['user'] == 'user' assert 'host' in result assert result['host'] == 'example.com' assert 'password' in result assert result['password'] == 'password' assert 'targets' in result assert isinstance(result['targets'], list) is True assert len(result['targets']) == 1 assert '#channel' in result['targets']
def test_fcm_plugin(mock_post): """ API: NotifyFCM() General Checks """ # Valid Keyfile path = os.path.join(PRIVATE_KEYFILE_DIR, 'service_account.json') # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 # Prepare a good response response = mock.Mock() response.content = json.dumps({ "access_token": "ya29.c.abcd", "expires_in": 3599, "token_type": "Bearer", }) response.status_code = requests.codes.ok mock_post.return_value = response # Test having a valid keyfile, but not a valid project id match obj = Apprise.instantiate( 'fcm://invalid_project_id/device/?keyfile={}'.format(str(path))) # we'll fail as a result assert obj.notify("test") is False # Test our call count assert mock_post.call_count == 0 # Now we test using a valid Project ID but we can't open our file obj = Apprise.instantiate( 'fcm://mock-project-id/device/?keyfile={}'.format(str(path))) with mock.patch('io.open', side_effect=OSError): # we'll fail as a result assert obj.notify("test") is False # Test our call count assert mock_post.call_count == 0 # Now we test using a valid Project ID obj = Apprise.instantiate( 'fcm://mock-project-id/device/#topic/?keyfile={}'.format(str(path))) # we'll fail as a result assert obj.notify("test") is True # Test our call count assert mock_post.call_count == 3 assert mock_post.call_args_list[0][0][0] == \ 'https://accounts.google.com/o/oauth2/token' assert mock_post.call_args_list[1][0][0] == \ 'https://fcm.googleapis.com/v1/projects/mock-project-id/messages:send' assert mock_post.call_args_list[2][0][0] == \ 'https://fcm.googleapis.com/v1/projects/mock-project-id/messages:send'
def test_smtplib_init_fail(mock_smtplib): """ API: Test exception handling when calling smtplib.SMTP() """ from apprise.plugins import NotifyEmailBase obj = Apprise.instantiate('mailto://*****:*****@gmail.com', suppress_exceptions=False) assert (isinstance(obj, plugins.NotifyEmail)) # Support Exception handling of smtplib.SMTP mock_smtplib.side_effect = TypeError('Test') try: obj.notify(title='test', body='body', notify_type=NotifyType.INFO) # We should have thrown an exception assert False except TypeError: # Exception thrown as expected assert True except Exception: # Un-Expected assert False # A handled and expected exception mock_smtplib.side_effect = smtplib.SMTPException('Test') assert obj.notify(title='test', body='body', notify_type=NotifyType.INFO) is False
def test_email_url_escaping(): """ API: Test that user/passwords are properly escaped from URL """ # quote(' %20') passwd = '%20%2520' # Basically we want to check that ' ' equates to %20 and % equates to %25 # So the above translates to ' %20' (a space in front of %20). We want # to verify the handling of the password escaping and when it happens. # a very bad response would be ' ' (double space) obj = plugins.NotifyEmail.parse_url( 'mailto://*****:*****@gmail.com?format=text'.format(passwd)) assert isinstance(obj, dict) is True assert 'password' in obj # Escaping doesn't happen at this stage because we want to leave this to # the plugins discretion assert obj.get('password') == '%20%2520' obj = Apprise.instantiate( 'mailto://*****:*****@gmail.com?format=text'.format(passwd), suppress_exceptions=False) assert isinstance(obj, plugins.NotifyEmail) is True # The password is escapped 'once' at this point assert obj.password == ' %20'
def test_webbase_lookup(mock_smtp, mock_smtpssl): """ API: Web Based Lookup Tests """ # Insert a test email at the head of our table NotifyEmailBase.WEBBASE_LOOKUP_TABLE = ( ( # Testing URL 'Testing Lookup', re.compile(r'^(?P<id>[^@]+)@(?P<domain>l2g\.com)$', re.I), { 'port': 123, 'smtp_host': 'smtp.l2g.com', 'secure': True, 'login_type': (NotifyEmailBase.WebBaseLogin.USERID, ) }, ), ) + NotifyEmailBase.WEBBASE_LOOKUP_TABLE obj = Apprise.instantiate('mailto://*****:*****@l2g.com', suppress_exceptions=True) assert (isinstance(obj, plugins.NotifyEmail)) assert obj.to_addr == '*****@*****.**' assert obj.from_addr == '*****@*****.**' assert obj.password == 'pass' assert obj.user == 'user' assert obj.secure is True assert obj.port == 123 assert obj.smtp_host == 'smtp.l2g.com'
def test_discord_attachments(mock_post): """ API: NotifyDiscord() Attachment Checks """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 # Initialize some generic (but valid) tokens webhook_id = 'C' * 24 webhook_token = 'D' * 64 # Prepare Mock return object response = mock.Mock() response.status_code = requests.codes.ok # Throw an exception on the second call to requests.post() mock_post.side_effect = [response, OSError()] # Test our markdown obj = Apprise.instantiate('discord://{}/{}/?format=markdown'.format( webhook_id, webhook_token)) # attach our content attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) # We'll fail now because of an internal exception assert obj.send(body="test", attach=attach) is False
def test_plugin_homeassistant_general(mock_post): """ NotifyHomeAssistant() General Checks """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 response = mock.Mock() response.content = '' response.status_code = requests.codes.ok # Prepare Mock mock_post.return_value = response # Variation Initializations obj = Apprise.instantiate('hassio://localhost/accesstoken') assert isinstance(obj, plugins.NotifyHomeAssistant) is True assert isinstance(obj.url(), six.string_types) is True # Send Notification assert obj.send(body="test") is True assert mock_post.call_count == 1 assert mock_post.call_args_list[0][0][0] == \ 'http://localhost:8123/api/services/persistent_notification/create'
def test_plugin_fcm_cryptography_import_error(): """ NotifySimplePush() Cryptography loading failure """ # Attempt to instantiate our object obj = Apprise.instantiate('spush://{}'.format('Y' * 14)) # It's not possible because our cryptography depedancy is missing assert obj is None
def test_plugin(mock_oauth, mock_api): """ API: NotifyTwitter Plugin() (pt1) """ # iterate over our dictionary and test it out for (url, meta) in TEST_URLS: # Our expected instance instance = meta.get('instance', 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 response = meta.get( 'response', True if response else False) try: obj = Apprise.instantiate(url, suppress_exceptions=False) if instance is None: # Check that we got what we came for assert obj is instance 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) # check that we're as expected assert obj.notify( title='test', body='body', notify_type=NotifyType.INFO) == response except AssertionError: # Don't mess with these entries raise except Exception as e: # Handle our exception assert(instance is not None) assert(isinstance(e, instance))
def test_email_dict_variations(): """ API: Test email dictionary variations to ensure parsing is correct """ # Test variations of username required to be an email address # [email protected] obj = Apprise.instantiate({ 'schema': 'mailto', 'user': '******', 'password': '******', 'host': 'example.com'}, suppress_exceptions=False) assert isinstance(obj, plugins.NotifyEmail) is True
def test_webbase_lookup(mock_smtp, mock_smtpssl): """ API: Web Based Lookup Tests """ # Insert a test email at the head of our table NotifyEmailBase.EMAIL_TEMPLATES = ( ( # Testing URL 'Testing Lookup', re.compile(r'^(?P<id>[^@]+)@(?P<domain>l2g\.com)$', re.I), { 'port': 123, 'smtp_host': 'smtp.l2g.com', 'secure': True, 'login_type': (NotifyEmailBase.WebBaseLogin.USERID, ) }, ), ) + NotifyEmailBase.EMAIL_TEMPLATES obj = Apprise.instantiate( 'mailto://*****:*****@l2g.com', suppress_exceptions=True) assert isinstance(obj, plugins.NotifyEmail) assert len(obj.targets) == 1 assert (False, '*****@*****.**') in obj.targets assert obj.from_addr == '*****@*****.**' assert obj.password == 'pass' assert obj.user == 'user' assert obj.secure is True assert obj.port == 123 assert obj.smtp_host == 'smtp.l2g.com' # We get the same results if an email is identified as the username # because the USERID variable forces that we can't use an email obj = Apprise.instantiate( 'mailto://*****:*****@[email protected]', suppress_exceptions=True) assert obj.user == 'user'
def test_discord_attachments(mock_post): """ API: NotifyDiscord() Attachment Checks """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 # Initialize some generic (but valid) tokens webhook_id = 'C' * 24 webhook_token = 'D' * 64 # Prepare Mock return object mock_post.return_value = requests.Request() mock_post.return_value.status_code = requests.codes.ok # Test our markdown obj = Apprise.instantiate('discord://{}/{}/?format=markdown'.format( webhook_id, webhook_token)) # attach our content attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) assert obj.notify( body='body', title='title', notify_type=NotifyType.INFO, attach=attach) is True # An invalid attachment will cause a failure path = os.path.join(TEST_VAR_DIR, '/invalid/path/to/an/invalid/file.jpg') attach = AppriseAttachment(path) assert obj.notify( body='body', title='title', notify_type=NotifyType.INFO, attach=path) is False # Throw an exception on the second call to requests.post() mock_post.return_value = None response = mock.Mock() response.status_code = requests.codes.ok mock_post.side_effect = [response, OSError()] # update our attachment to be valid attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) # Test our markdown # We'll fail now because of an internal exception assert obj.send(body="test", attach=attach) is False
def test_plugin_ses_attachments(mock_post): """ NotifySES() Attachment Checks """ # Disable Throttling to speed testing plugins.NotifySES.request_rate_per_sec = 0 # Prepare Mock return object response = mock.Mock() response.content = AWS_SES_GOOD_RESPONSE response.status_code = requests.codes.ok mock_post.return_value = response # prepare our attachment attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) # Test our markdown obj = Apprise.instantiate('ses://%s/%s/%s/%s/' % ('*****@*****.**', TEST_ACCESS_KEY_ID, TEST_ACCESS_KEY_SECRET, TEST_REGION)) # Send a good attachment assert obj.notify(body="test", attach=attach) is True # Reset our mock object mock_post.reset_mock() # Add another attachment so we drop into the area of the PushBullet code # that sends remaining attachments (if more detected) attach.add(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) # Send our attachments assert obj.notify(body="test", attach=attach) is True # Test our call count assert mock_post.call_count == 1 # Reset our mock object mock_post.reset_mock() # An invalid attachment will cause a failure path = os.path.join(TEST_VAR_DIR, '/invalid/path/to/an/invalid/file.jpg') attach = AppriseAttachment(path) assert obj.notify(body="test", attach=attach) is False
def test_smtplib_send_okay(mock_smtplib): """ API: Test a successfully sent email """ from apprise.plugins import NotifyEmailBase obj = Apprise.instantiate('mailto://*****:*****@gmail.com', suppress_exceptions=False) assert (isinstance(obj, plugins.NotifyEmail)) # Support an email simulation where we can correctly quit mock_smtplib.starttls.return_value = True mock_smtplib.login.return_value = True mock_smtplib.sendmail.return_value = True mock_smtplib.quit.return_value = True obj.notify(title='test', body='body', notify_type=NotifyType.INFO)
def test_plugin_simplepush_general(mock_post): """ NotifySimplePush() General Tests """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 # Prepare a good response response = mock.Mock() response.content = json.dumps({ 'status': 'OK', }) response.status_code = requests.codes.ok mock_post.return_value = response obj = Apprise.instantiate('spush://{}'.format('Y' * 14)) # Verify our content works as expected assert obj.notify(title="test", body="test") is True
def test_smtplib_init_fail(mock_smtplib): """ API: Test exception handling when calling smtplib.SMTP() """ # Disable Throttling to speed testing plugins.NotifyBase.NotifyBase.request_rate_per_sec = 0 obj = Apprise.instantiate('mailto://*****:*****@gmail.com', suppress_exceptions=False) assert (isinstance(obj, plugins.NotifyEmail)) # Support Exception handling of smtplib.SMTP mock_smtplib.side_effect = RuntimeError('Test') assert obj.notify(body='body', title='test', notify_type=NotifyType.INFO) is False # A handled and expected exception mock_smtplib.side_effect = smtplib.SMTPException('Test') assert obj.notify(body='body', title='test', notify_type=NotifyType.INFO) is False
def test_plugin_emby_sessions(mock_post, mock_get, mock_logout, mock_login): """ NotifyEmby() sessions() """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 # Prepare Mock mock_get.return_value = requests.Request() mock_post.return_value = requests.Request() # This is done so we don't obstruct our access_token and user_id values mock_login.return_value = True mock_logout.return_value = True obj = Apprise.instantiate('emby://*****:*****@localhost') assert isinstance(obj, plugins.NotifyEmby) obj.access_token = 'abc' obj.user_id = '123' # Test our exception handling for _exception in AppriseURLTester.req_exceptions: mock_post.side_effect = _exception mock_get.side_effect = _exception # We'll fail to log in each time sessions = obj.sessions() assert isinstance(sessions, dict) is True assert len(sessions) == 0 # Disable Exceptions mock_post.side_effect = None mock_get.side_effect = None # Our login flat out fails if we don't have proper parseable content mock_post.return_value.content = u'' mock_get.return_value.content = mock_post.return_value.content # KeyError handling mock_post.return_value.status_code = 999 mock_get.return_value.status_code = 999 sessions = obj.sessions() assert isinstance(sessions, dict) is True assert len(sessions) == 0 # General Internal Server Error mock_post.return_value.status_code = requests.codes.internal_server_error mock_get.return_value.status_code = requests.codes.internal_server_error sessions = obj.sessions() assert isinstance(sessions, dict) is True assert len(sessions) == 0 mock_post.return_value.status_code = requests.codes.ok mock_get.return_value.status_code = requests.codes.ok mock_get.return_value.content = mock_post.return_value.content # Disable the port completely obj.port = None sessions = obj.sessions() assert isinstance(sessions, dict) is True assert len(sessions) == 0 # Let's get some results mock_post.return_value.content = dumps([ { u'Id': u'abc123', }, { u'Id': u'def456', }, { u'InvalidEntry': None, }, ]) mock_get.return_value.content = mock_post.return_value.content sessions = obj.sessions(user_controlled=True) assert isinstance(sessions, dict) is True assert len(sessions) == 2 # Test it without setting user-controlled sessions sessions = obj.sessions(user_controlled=False) assert isinstance(sessions, dict) is True assert len(sessions) == 2 # Triggers an authentication failure obj.user_id = None mock_login.return_value = False sessions = obj.sessions() assert isinstance(sessions, dict) is True assert len(sessions) == 0
def test_smtplib_internationalization(mock_smtp): """ API: Test email handling using internationalization """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 # Defaults to HTML obj = Apprise.instantiate( 'mailto://*****:*****@gmail.com?name=Например%20так', suppress_exceptions=False) assert isinstance(obj, plugins.NotifyEmail) class SMTPMock(object): def sendmail(self, *args, **kwargs): """ over-ride sendmail calls so we can check our our internationalization formatting went """ match_subject = re.search( r'\n?(?P<line>Subject: (?P<subject>(.+?)))\n(?:[a-z0-9-]+:)', args[2], re.I | re.M | re.S) assert match_subject is not None match_from = re.search( r'^(?P<line>From: (?P<name>.+) <(?P<email>[^>]+)>)$', args[2], re.I | re.M) assert match_from is not None # Verify our output was correctly stored assert match_from.group('email') == '*****@*****.**' if six.PY2: # Python 2.x (backwards compatible) assert decode_header(match_from.group('name'))[0][0]\ .decode('utf-8') == u'Например так' assert decode_header(match_subject.group('subject'))[0][0]\ .decode('utf-8') == u'دعونا نجعل العالم مكانا أفضل.' else: # Python 3+ assert decode_header(match_from.group('name'))[0][0]\ .decode('utf-8') == 'Например так' assert decode_header(match_subject.group('subject'))[0][0]\ .decode('utf-8') == 'دعونا نجعل العالم مكانا أفضل.' # Dummy Function def quit(self, *args, **kwargs): return True # Dummy Function def starttls(self, *args, **kwargs): return True # Dummy Function def login(self, *args, **kwargs): return True # Prepare our object we will test our generated email against mock_smtp.return_value = SMTPMock() # Further test encoding through the message content as well assert obj.notify( # Google Translated to Arabic: "Let's make the world a better place." title='دعونا نجعل العالم مكانا أفضل.', # Google Translated to Hungarian: "One line of code at a time.' body='Egy sor kódot egyszerre.', notify_type=NotifyType.INFO) is True
def test_plugin(mock_refresh, mock_send): """ API: NotifyPushjet Plugin() (pt1) """ # iterate over our dictionary and test it out for (url, meta) in TEST_URLS: # Our expected instance instance = meta.get('instance', 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 response = meta.get( 'response', True if response else False) test_notify_exceptions = meta.get( 'test_notify_exceptions', False) test_exceptions = ( plugins.pushjet.errors.AccessError( 0, 'pushjet.AccessError() not handled'), plugins.pushjet.errors.NonexistentError( 0, 'pushjet.NonexistentError() not handled'), plugins.pushjet.errors.SubscriptionError( 0, 'gntp.SubscriptionError() not handled'), plugins.pushjet.errors.RequestError( 'pushjet.RequestError() not handled'), ) try: obj = Apprise.instantiate(url, suppress_exceptions=False) if obj is None: if instance is not None: # We're done (assuming this is what we were expecting) print("{} didn't instantiate itself " "(we expected it to)".format(url)) assert False continue if instance is None: # Expected None but didn't get it print('%s instantiated %s (but expected None)' % ( url, str(obj))) assert(False) assert(isinstance(obj, instance)) if isinstance(obj, plugins.NotifyBase): # We loaded okay; now lets make sure we can reverse this url assert(isinstance(obj.url(), six.string_types) is True) # Instantiate the exact same object again using the URL from # the one that was already created properly obj_cmp = Apprise.instantiate(obj.url()) # Our object should be the same instance as what we had # originally expected above. if not isinstance(obj_cmp, plugins.NotifyBase): # Assert messages are hard to trace back with the way # these tests work. Just printing before throwing our # assertion failure makes things easier to debug later on print('TEST FAIL: {} regenerated as {}'.format( url, obj.url())) assert(False) 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_notify_exceptions is False: # Store our response mock_send.return_value = response mock_send.side_effect = None # check that we're as expected assert obj.notify( title='test', body='body', notify_type=NotifyType.INFO) == response else: for exception in test_exceptions: mock_send.side_effect = exception mock_send.return_value = None 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: # We can't handle this exception type raise except AssertionError: # Don't mess with these entries print('%s AssertionError' % url) raise except Exception as e: # Check that we were expecting this exception to happen if not isinstance(e, response): raise except AssertionError: # Don't mess with these entries print('%s AssertionError' % url) raise except Exception as e: # Handle our exception if(instance is None): raise if not isinstance(e, instance): raise
def test_email_plugin(mock_smtp, mock_smtpssl): """ API: NotifyEmail Plugin() """ # Disable Throttling to speed testing plugins.NotifyBase.NotifyBase.request_rate_per_sec = 0 # iterate over our dictionary and test it out for (url, meta) in TEST_URLS: # Our expected instance instance = meta.get('instance', None) # Our expected server objects self = meta.get('self', None) # Our expected Query response (True, False, or exception type) response = meta.get('response', True) test_smtplib_exceptions = meta.get('test_smtplib_exceptions', False) # Our mock of our socket action mock_socket = mock.Mock() mock_socket.starttls.return_value = True mock_socket.login.return_value = True # Create a mock SMTP Object mock_smtp.return_value = mock_socket mock_smtpssl.return_value = mock_socket if test_smtplib_exceptions: # Handle exception testing; first we turn the boolean flag ito # a list of exceptions test_smtplib_exceptions = ( smtplib.SMTPHeloError(0, 'smtplib.SMTPHeloError() not handled'), smtplib.SMTPException(0, 'smtplib.SMTPException() not handled'), RuntimeError(0, 'smtplib.HTTPError() not handled'), smtplib.SMTPRecipientsRefused( 'smtplib.SMTPRecipientsRefused() not handled'), smtplib.SMTPSenderRefused( 0, 'smtplib.SMTPSenderRefused() not handled', '*****@*****.**'), smtplib.SMTPDataError(0, 'smtplib.SMTPDataError() not handled'), smtplib.SMTPServerDisconnected( 'smtplib.SMTPServerDisconnected() not handled'), ) try: obj = Apprise.instantiate(url, suppress_exceptions=False) if obj is None: # We're done (assuming this is what we were expecting) assert instance is None continue if instance is None: # Expected None but didn't get it print('%s instantiated %s (but expected None)' % (url, str(obj))) assert (False) assert (isinstance(obj, instance)) if isinstance(obj, plugins.NotifyBase.NotifyBase): # We loaded okay; now lets make sure we can reverse this url assert (isinstance(obj.url(), six.string_types) is True) # Instantiate the exact same object again using the URL from # the one that was already created properly obj_cmp = Apprise.instantiate(obj.url()) # Our object should be the same instance as what we had # originally expected above. if not isinstance(obj_cmp, plugins.NotifyBase.NotifyBase): # Assert messages are hard to trace back with the way # these tests work. Just printing before throwing our # assertion failure makes things easier to debug later on print('TEST FAIL: {} regenerated as {}'.format( url, obj.url())) assert (False) 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_smtplib_exceptions is False: # check that we're as expected assert obj.notify(title='test', body='body', notify_type=NotifyType.INFO) == response else: for exception in test_smtplib_exceptions: mock_socket.sendmail.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: # We can't handle this exception type raise except AssertionError: # Don't mess with these entries print('%s AssertionError' % url) raise except Exception as e: # Check that we were expecting this exception to happen if not isinstance(e, response): raise except AssertionError: # Don't mess with these entries print('%s AssertionError' % url) raise except Exception as e: # Handle our exception if (instance is None): raise if not isinstance(e, instance): raise
def test_apprise(): """ API: Apprise() object """ # Caling load matix a second time which is an internal function causes it # to skip over content already loaded into our matrix and thefore accesses # other if/else parts of the code that aren't otherwise called __load_matrix() a = Apprise() # no items assert (len(a) == 0) # Create an Asset object asset = AppriseAsset(theme='default') # We can load the device using our asset a = Apprise(asset=asset) # We can load our servers up front as well servers = [ 'faast://abcdefghijklmnop-abcdefg', 'kodi://kodi.server.local', ] a = Apprise(servers=servers) # 2 servers loaded assert (len(a) == 2) # We can retrieve our URLs this way: assert (len(a.urls()) == 2) # We can add another server assert (a.add('mmosts://mattermost.server.local/' '3ccdd113474722377935511fc85d3dd4') is True) assert (len(a) == 3) # We can pop an object off of our stack by it's indexed value: obj = a.pop(0) assert (isinstance(obj, NotifyBase) is True) assert (len(a) == 2) # We can retrieve elements from our list too by reference: assert (isinstance(a[0].url(), six.string_types) is True) # We can iterate over our list too: count = 0 for o in a: assert (isinstance(o.url(), six.string_types) is True) count += 1 # verify that we did indeed iterate over each element assert (len(a) == count) # We can empty our set a.clear() assert (len(a) == 0) # An invalid schema assert (a.add('this is not a parseable url at all') is False) assert (len(a) == 0) # An unsupported schema assert (a.add('invalid://we.just.do.not.support.this.plugin.type') is False) assert (len(a) == 0) # A poorly formatted URL assert (a.add('json://user:@@@:bad?no.good') is False) assert (len(a) == 0) # Add a server with our asset we created earlier assert (a.add( 'mmosts://mattermost.server.local/' '3ccdd113474722377935511fc85d3dd4', asset=asset) is True) # Clear our server listings again a.clear() # No servers to notify assert (a.notify(title="my title", body="my body") is False) class BadNotification(NotifyBase): def __init__(self, **kwargs): super(BadNotification, self).__init__(**kwargs) # We fail whenever we're initialized raise TypeError() def url(self): # Support URL return '' class GoodNotification(NotifyBase): def __init__(self, **kwargs): super(GoodNotification, self).__init__(notify_format=NotifyFormat.HTML, **kwargs) def url(self): # Support URL return '' def notify(self, **kwargs): # Pretend everything is okay return True # Store our bad notification in our schema map SCHEMA_MAP['bad'] = BadNotification # Store our good notification in our schema map SCHEMA_MAP['good'] = GoodNotification # Just to explain what is happening here, we would have parsed the # url properly but failed when we went to go and create an instance # of it. assert (a.add('bad://localhost') is False) assert (len(a) == 0) assert (a.add('good://localhost') is True) assert (len(a) == 1) # Bad Notification Type is still allowed as it is presumed the user # know's what their doing assert (a.notify(title="my title", body="my body", notify_type='bad') is True) # No Title/Body combo's assert (a.notify(title=None, body=None) is False) assert (a.notify(title='', body=None) is False) assert (a.notify(title=None, body='') is False) # As long as one is present, we're good assert (a.notify(title=None, body='present') is True) assert (a.notify(title='present', body=None) is True) assert (a.notify(title="present", body="present") is True) # Clear our server listings again a.clear() class ThrowNotification(NotifyBase): def notify(self, **kwargs): # Pretend everything is okay raise TypeError() def url(self): # Support URL return '' class RuntimeNotification(NotifyBase): def notify(self, **kwargs): # Pretend everything is okay raise RuntimeError() def url(self): # Support URL return '' class FailNotification(NotifyBase): def notify(self, **kwargs): # Pretend everything is okay return False def url(self): # Support URL return '' # Store our bad notification in our schema map SCHEMA_MAP['throw'] = ThrowNotification # Store our good notification in our schema map SCHEMA_MAP['fail'] = FailNotification # Store our good notification in our schema map SCHEMA_MAP['runtime'] = RuntimeNotification assert (a.add('runtime://localhost') is True) assert (a.add('throw://localhost') is True) assert (a.add('fail://localhost') is True) assert (len(a) == 3) # Test when our notify both throws an exception and or just # simply returns False assert (a.notify(title="present", body="present") is False) # Create a Notification that throws an unexected exception class ThrowInstantiateNotification(NotifyBase): def __init__(self, **kwargs): # Pretend everything is okay raise TypeError() def url(self): # Support URL return '' SCHEMA_MAP['throw'] = ThrowInstantiateNotification # Reset our object a.clear() assert (len(a) == 0) # Instantiate a bad object plugin = a.instantiate(object, tag="bad_object") assert plugin is None # Instantiate a good object plugin = a.instantiate('good://localhost', tag="good") assert (isinstance(plugin, NotifyBase)) # Test simple tagging inside of the object assert ("good" in plugin) assert ("bad" not in plugin) # the in (__contains__ override) is based on or'ed content; so although # 'bad' isn't tagged as being in the plugin, 'good' is, so the return # value of this is True assert (["bad", "good"] in plugin) assert (set(["bad", "good"]) in plugin) assert (("bad", "good") in plugin) # We an add already substatiated instances into our Apprise object a.add(plugin) assert (len(a) == 1) # We can add entries as a list too (to add more then one) a.add([plugin, plugin, plugin]) assert (len(a) == 4) # Reset our object again a.clear() try: a.instantiate('throw://localhost', suppress_exceptions=False) assert (False) except TypeError: assert (True) assert (len(a) == 0) assert (a.instantiate('throw://localhost', suppress_exceptions=True) is None) assert (len(a) == 0) # # We rince and repeat the same tests as above, however we do them # using the dict version # # Reset our object a.clear() assert (len(a) == 0) # Instantiate a good object plugin = a.instantiate({'schema': 'good', 'host': 'localhost'}, tag="good") assert (isinstance(plugin, NotifyBase)) # Test simple tagging inside of the object assert ("good" in plugin) assert ("bad" not in plugin) # the in (__contains__ override) is based on or'ed content; so although # 'bad' isn't tagged as being in the plugin, 'good' is, so the return # value of this is True assert (["bad", "good"] in plugin) assert (set(["bad", "good"]) in plugin) assert (("bad", "good") in plugin) # We an add already substatiated instances into our Apprise object a.add(plugin) assert (len(a) == 1) # We can add entries as a list too (to add more then one) a.add([plugin, plugin, plugin]) assert (len(a) == 4) # Reset our object again a.clear() try: a.instantiate({ 'schema': 'throw', 'host': 'localhost' }, suppress_exceptions=False) assert (False) except TypeError: assert (True) assert (len(a) == 0) assert (a.instantiate({ 'schema': 'throw', 'host': 'localhost' }, suppress_exceptions=True) is None) assert (len(a) == 0)
def test_plugin_pushover_attachments(mock_post, tmpdir): """ NotifyPushover() Attachment Checks """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 # Initialize some generic (but valid) tokens user_key = 'u' * 30 api_token = 'a' * 30 # Prepare a good response response = mock.Mock() response.content = dumps( {"status": 1, "request": "647d2300-702c-4b38-8b2f-d56326ae460b"}) response.status_code = requests.codes.ok # Prepare a bad response bad_response = mock.Mock() response.content = dumps( {"status": 1, "request": "647d2300-702c-4b38-8b2f-d56326ae460b"}) bad_response.status_code = requests.codes.internal_server_error # Assign our good response mock_post.return_value = response # prepare our attachment attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) # Instantiate our object obj = Apprise.instantiate( 'pover://{}@{}/'.format(user_key, api_token)) assert isinstance(obj, plugins.NotifyPushover) # Test our attachment assert obj.notify(body="test", attach=attach) is True # Test our call count assert mock_post.call_count == 1 assert mock_post.call_args_list[0][0][0] == \ 'https://api.pushover.net/1/messages.json' # Reset our mock object for multiple tests mock_post.reset_mock() # Test multiple attachments assert attach.add(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) assert obj.notify(body="test", attach=attach) is True # Test our call count assert mock_post.call_count == 2 assert mock_post.call_args_list[0][0][0] == \ 'https://api.pushover.net/1/messages.json' assert mock_post.call_args_list[1][0][0] == \ 'https://api.pushover.net/1/messages.json' # Reset our mock object for multiple tests mock_post.reset_mock() image = tmpdir.mkdir("pover_image").join("test.jpg") image.write('a' * plugins.NotifyPushover.attach_max_size_bytes) attach = AppriseAttachment.instantiate(str(image)) assert obj.notify(body="test", attach=attach) is True # Test our call count assert mock_post.call_count == 1 assert mock_post.call_args_list[0][0][0] == \ 'https://api.pushover.net/1/messages.json' # Reset our mock object for multiple tests mock_post.reset_mock() # Add 1 more byte to the file (putting it over the limit) image.write('a' * (plugins.NotifyPushover.attach_max_size_bytes + 1)) attach = AppriseAttachment.instantiate(str(image)) assert obj.notify(body="test", attach=attach) is False # Test our call count assert mock_post.call_count == 0 # Test case when file is missing attach = AppriseAttachment.instantiate( 'file://{}?cache=False'.format(str(image))) os.unlink(str(image)) assert obj.notify( body='body', title='title', attach=attach) is False # Test our call count assert mock_post.call_count == 0 # Test unsuported files: image = tmpdir.mkdir("pover_unsupported").join("test.doc") image.write('a' * 256) attach = AppriseAttachment.instantiate(str(image)) # Content is silently ignored assert obj.notify(body="test", attach=attach) is True # prepare our attachment attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) # Throw an exception on the first call to requests.post() for side_effect in (requests.RequestException(), OSError(), bad_response): mock_post.side_effect = [side_effect, side_effect] # We'll fail now because of our error handling assert obj.send(body="test", attach=attach) is False # Same case without an attachment assert obj.send(body="test") is False
def test_email_url_variations(): """ API: Test email variations to ensure parsing is correct """ # Test variations of username required to be an email address # [email protected] obj = Apprise.instantiate('mailto://{user}:{passwd}@example.com'.format( user='******', passwd='abcd123'), suppress_exceptions=False) assert isinstance(obj, plugins.NotifyEmail) is True assert obj.password == 'abcd123' assert obj.user == '*****@*****.**' # test username specified in the url body (as an argument) # this always over-rides the entry at the front of the url obj = Apprise.instantiate( 'mailto://*****:*****@example.com?user={user}'.format( user='******', passwd='abcd123'), suppress_exceptions=False) assert isinstance(obj, plugins.NotifyEmail) is True assert obj.password == 'abcd123' assert obj.user == '*****@*****.**' # test user and password specified in the url body (as an argument) # this always over-rides the entries at the front of the url obj = Apprise.instantiate( 'mailto://*****:*****@example.com?user={user}&pass={passwd}'.format( user='******', passwd='abcd123'), suppress_exceptions=False) assert isinstance(obj, plugins.NotifyEmail) is True assert obj.password == 'abcd123' assert obj.user == '*****@*****.**' assert len(obj.targets) == 1 assert '*****@*****.**' in obj.targets assert obj.targets[0] == obj.from_addr # test user and password specified in the url body (as an argument) # this always over-rides the entries at the front of the url # this is similar to the previous test except we're only specifying # this information in the kwargs obj = Apprise.instantiate( 'mailto://example.com?user={user}&pass={passwd}'.format( user='******', passwd='abcd123'), suppress_exceptions=False) assert isinstance(obj, plugins.NotifyEmail) is True assert obj.password == 'abcd123' assert obj.user == '*****@*****.**' assert len(obj.targets) == 1 assert '*****@*****.**' in obj.targets assert obj.targets[0] == obj.from_addr assert obj.smtp_host == 'example.com' # test a complicated example obj = Apprise.instantiate( 'mailtos://{user}:{passwd}@{host}:{port}' '?smtp={smtp_host}&format=text&from={this}&to={that}'.format( user='******', passwd='abcd123', host='example.com', port=1234, this='*****@*****.**', that='*****@*****.**', smtp_host='smtp.example.edu'), suppress_exceptions=False) assert isinstance(obj, plugins.NotifyEmail) is True assert obj.password == 'abcd123' assert obj.user == '*****@*****.**' assert obj.host == 'example.com' assert obj.port == 1234 assert obj.smtp_host == 'smtp.example.edu' assert len(obj.targets) == 1 assert '*****@*****.**' in obj.targets assert obj.from_addr == '*****@*****.**'
def test_plugin_emby_logout(mock_post, mock_get, mock_login): """ NotifyEmby() logout() """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 # Prepare Mock mock_get.return_value = requests.Request() mock_post.return_value = requests.Request() # This is done so we don't obstruct our access_token and user_id values mock_login.return_value = True obj = Apprise.instantiate('emby://*****:*****@localhost') assert isinstance(obj, plugins.NotifyEmby) obj.access_token = 'abc' obj.user_id = '123' # Test our exception handling for _exception in AppriseURLTester.req_exceptions: mock_post.side_effect = _exception mock_get.side_effect = _exception # We'll fail to log in each time obj.logout() obj.access_token = 'abc' obj.user_id = '123' # Disable Exceptions mock_post.side_effect = None mock_get.side_effect = None # Our login flat out fails if we don't have proper parseable content mock_post.return_value.content = u'' mock_get.return_value.content = mock_post.return_value.content # KeyError handling mock_post.return_value.status_code = 999 mock_get.return_value.status_code = 999 obj.logout() obj.access_token = 'abc' obj.user_id = '123' # General Internal Server Error mock_post.return_value.status_code = requests.codes.internal_server_error mock_get.return_value.status_code = requests.codes.internal_server_error obj.logout() obj.access_token = 'abc' obj.user_id = '123' mock_post.return_value.status_code = requests.codes.ok mock_get.return_value.status_code = requests.codes.ok mock_get.return_value.content = mock_post.return_value.content # Disable the port completely obj.port = None # Perform logout obj.logout() # Calling logout on an object already logged out obj.logout() # Test Python v3.5 LookupError Bug: https://bugs.python.org/issue29288 mock_post.side_effect = LookupError() mock_get.side_effect = LookupError() obj.access_token = 'abc' obj.user_id = '123' # Tidy object del obj
def test_plugin_emby_general(mock_post, mock_get, mock_logout, mock_login, mock_sessions): """ NotifyEmby General Tests """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 req = requests.Request() req.status_code = requests.codes.ok req.content = '' mock_get.return_value = req mock_post.return_value = req # This is done so we don't obstruct our access_token and user_id values mock_login.return_value = True mock_logout.return_value = True mock_sessions.return_value = {'abcd': {}} obj = Apprise.instantiate('emby://*****:*****@localhost?modal=False') assert isinstance(obj, plugins.NotifyEmby) assert obj.notify('title', 'body', 'info') is True obj.access_token = 'abc' obj.user_id = '123' # Test Modal support obj = Apprise.instantiate('emby://*****:*****@localhost?modal=True') assert isinstance(obj, plugins.NotifyEmby) assert obj.notify('title', 'body', 'info') is True obj.access_token = 'abc' obj.user_id = '123' # Test our exception handling for _exception in AppriseURLTester.req_exceptions: mock_post.side_effect = _exception mock_get.side_effect = _exception # We'll fail to log in each time assert obj.notify('title', 'body', 'info') is False # Disable Exceptions mock_post.side_effect = None mock_get.side_effect = None # Our login flat out fails if we don't have proper parseable content mock_post.return_value.content = u'' mock_get.return_value.content = mock_post.return_value.content # KeyError handling mock_post.return_value.status_code = 999 mock_get.return_value.status_code = 999 assert obj.notify('title', 'body', 'info') is False # General Internal Server Error mock_post.return_value.status_code = requests.codes.internal_server_error mock_get.return_value.status_code = requests.codes.internal_server_error assert obj.notify('title', 'body', 'info') is False mock_post.return_value.status_code = requests.codes.ok mock_get.return_value.status_code = requests.codes.ok mock_get.return_value.content = mock_post.return_value.content # Disable the port completely obj.port = None assert obj.notify('title', 'body', 'info') is True # An Empty return set (no query is made, but notification will still # succeed mock_sessions.return_value = {} assert obj.notify('title', 'body', 'info') is True # Tidy our object del obj
def test_smtplib_send_okay(mock_smtplib): """ API: Test a successfully sent email """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 # Defaults to HTML obj = Apprise.instantiate('mailto://*****:*****@gmail.com', suppress_exceptions=False) assert isinstance(obj, plugins.NotifyEmail) # Support an email simulation where we can correctly quit mock_smtplib.starttls.return_value = True mock_smtplib.login.return_value = True mock_smtplib.sendmail.return_value = True mock_smtplib.quit.return_value = True assert obj.notify(body='body', title='test', notify_type=NotifyType.INFO) is True # Set Text obj = Apprise.instantiate('mailto://*****:*****@gmail.com?format=text', suppress_exceptions=False) assert isinstance(obj, plugins.NotifyEmail) assert obj.notify(body='body', title='test', notify_type=NotifyType.INFO) is True # Create an apprise object to work with as well a = Apprise() assert a.add('mailto://*****:*****@gmail.com?format=text') # Send Attachment with success attach = os.path.join(TEST_VAR_DIR, 'apprise-test.gif') assert obj.notify( body='body', title='test', notify_type=NotifyType.INFO, attach=attach) is True # same results happen from our Apprise object assert a.notify(body='body', title='test', attach=attach) is True # test using an Apprise Attachment object assert obj.notify(body='body', title='test', notify_type=NotifyType.INFO, attach=AppriseAttachment(attach)) is True # same results happen from our Apprise object assert a.notify( body='body', title='test', attach=AppriseAttachment(attach)) is True max_file_size = AttachBase.max_file_size # Now do a case where the file can't be sent AttachBase.max_file_size = 1 assert obj.notify( body='body', title='test', notify_type=NotifyType.INFO, attach=attach) is False # same results happen from our Apprise object assert a.notify(body='body', title='test', attach=attach) is False # Restore value AttachBase.max_file_size = max_file_size
def test_email_plugin(mock_smtp, mock_smtpssl): """ API: NotifyEmail Plugin() """ # iterate over our dictionary and test it out for (url, meta) in TEST_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) test_smtplib_exceptions = meta.get('test_smtplib_exceptions', False) # Our mock of our socket action mock_socket = mock.Mock() mock_socket.starttls.return_value = True mock_socket.login.return_value = True # Create a mock SMTP Object mock_smtp.return_value = mock_socket mock_smtpssl.return_value = mock_socket if test_smtplib_exceptions: # Handle exception testing; first we turn the boolean flag ito # a list of exceptions test_smtplib_exceptions = ( smtplib.SMTPHeloError(0, 'smtplib.SMTPHeloError() not handled'), smtplib.SMTPException(0, 'smtplib.SMTPException() not handled'), RuntimeError(0, 'smtplib.HTTPError() not handled'), smtplib.SMTPRecipientsRefused( 'smtplib.SMTPRecipientsRefused() not handled'), smtplib.SMTPSenderRefused( 0, 'smtplib.SMTPSenderRefused() not handled', '*****@*****.**'), smtplib.SMTPDataError(0, 'smtplib.SMTPDataError() not handled'), smtplib.SMTPServerDisconnected( 'smtplib.SMTPServerDisconnected() not handled'), ) try: obj = Apprise.instantiate(url, suppress_exceptions=False) assert (exception is None) if obj is None: # We're done continue if instance is None: # Expected None but didn't get it print('%s instantiated %s' % (url, str(obj))) assert (False) 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_smtplib_exceptions is False: # check that we're as expected assert obj.notify(title='test', body='body', notify_type=NotifyType.INFO) == response else: for exception in test_smtplib_exceptions: mock_socket.sendmail.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 print('%s / %s' % (url, str(e))) 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 print('%s AssertionError' % url) raise except Exception as e: # Handle our exception print('%s / %s' % (url, str(e))) assert (exception is not None) assert (isinstance(e, exception))
def test_pushbullet_attachments(mock_post): """ API: NotifyPushBullet() Attachment Checks """ # Disable Throttling to speed testing plugins.NotifyBase.request_rate_per_sec = 0 # Initialize some generic (but valid) tokens access_token = 't' * 32 # Prepare Mock return object response = mock.Mock() response.content = dumps({ "file_name": "cat.jpg", "file_type": "image/jpeg", "file_url": "https://dl.pushb.com/abc/cat.jpg", "upload_url": "https://upload.pushbullet.com/abcd123", }) response.status_code = requests.codes.ok mock_post.return_value = response # prepare our attachment attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) # Test our markdown obj = Apprise.instantiate( 'pbul://{}/?format=markdown'.format(access_token)) # Send a good attachment assert obj.notify(body="test", attach=attach) is True # Add another attachment so we drop into the area of the PushBullet code # that sends remaining attachments (if more detected) attach.add(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) # Send our attachments assert obj.notify(body="test", attach=attach) is True # An invalid attachment will cause a failure path = os.path.join(TEST_VAR_DIR, '/invalid/path/to/an/invalid/file.jpg') attach = AppriseAttachment(path) assert obj.notify(body="test", attach=attach) is False # Throw an exception on the first call to requests.post() mock_post.return_value = None mock_post.side_effect = requests.RequestException() # We'll fail now because of an internal exception assert obj.send(body="test", attach=attach) is False # Throw an exception on the second call to requests.post() mock_post.side_effect = [response, OSError()] # We'll fail now because of an internal exception assert obj.send(body="test", attach=attach) is False # Throw an exception on the third call to requests.post() mock_post.side_effect = [ response, response, requests.RequestException()] # We'll fail now because of an internal exception assert obj.send(body="test", attach=attach) is False # Throw an exception on the forth call to requests.post() mock_post.side_effect = [ response, response, response, requests.RequestException()] # We'll fail now because of an internal exception assert obj.send(body="test", attach=attach) is False # Test case where we don't get a valid response back response.content = '}' mock_post.side_effect = response # We'll fail because of an invalid json object assert obj.send(body="test", attach=attach) is False # # Test bad responses # # Prepare a bad response response.content = dumps({ "file_name": "cat.jpg", "file_type": "image/jpeg", "file_url": "https://dl.pushb.com/abc/cat.jpg", "upload_url": "https://upload.pushbullet.com/abcd123", }) bad_response = mock.Mock() bad_response.content = response.content bad_response.status_code = 400 # Throw an exception on the third call to requests.post() mock_post.return_value = bad_response # prepare our attachment attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, 'apprise-test.gif')) # We'll fail now because we were unable to send the attachment assert obj.send(body="test", attach=attach) is False # Throw an exception on the second call mock_post.side_effect = [response, bad_response, response] assert obj.send(body="test", attach=attach) is False # Throw an OSError mock_post.side_effect = [response, OSError()] assert obj.send(body="test", attach=attach) is False # Throw an exception on the third call mock_post.side_effect = [response, response, bad_response] assert obj.send(body="test", attach=attach) is False # Throw an exception on the fourth call mock_post.side_effect = [response, response, response, bad_response] assert obj.send(body="test", attach=attach) is False # A good message mock_post.side_effect = [response, response, response, response] assert obj.send(body="test", attach=attach) is True
def test_plugin(mock_refresh, mock_send): """ API: NotifyPushjet Plugin() (pt1) """ # iterate over our dictionary and test it out for (url, meta) in TEST_URLS: # Our expected instance instance = meta.get('instance', 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 response = meta.get('response', True if response else False) test_notify_exceptions = meta.get('test_notify_exceptions', False) test_exceptions = ( plugins.pushjet.errors.AccessError( 0, 'pushjet.AccessError() not handled'), plugins.pushjet.errors.NonexistentError( 0, 'pushjet.NonexistentError() not handled'), plugins.pushjet.errors.SubscriptionError( 0, 'gntp.SubscriptionError() not handled'), plugins.pushjet.errors.RequestError( 'pushjet.RequestError() not handled'), ) try: obj = Apprise.instantiate(url, suppress_exceptions=False) if instance is None: # Check that we got what we came for assert obj is instance 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_notify_exceptions is False: # Store our response mock_send.return_value = response mock_send.side_effect = None # check that we're as expected assert obj.notify(title='test', body='body', notify_type=NotifyType.INFO) == response else: for exception in test_exceptions: mock_send.side_effect = exception mock_send.return_value = None 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 (instance is not None) assert (isinstance(e, instance))