NotifyEmail unit tests

This commit is contained in:
Chris Caron 2017-12-06 00:35:03 -05:00
parent 9438f1c194
commit 6cca5946e1
8 changed files with 427 additions and 97 deletions

View File

@ -33,6 +33,7 @@ except ImportError:
from ..utils import parse_url from ..utils import parse_url
from ..utils import parse_bool from ..utils import parse_bool
from ..utils import is_hostname
from ..common import NOTIFY_IMAGE_SIZES from ..common import NOTIFY_IMAGE_SIZES
from ..common import NOTIFY_TYPES from ..common import NOTIFY_TYPES
@ -80,8 +81,8 @@ NOTIFY_FORMATS = (
# Regular expression retrieved from: # Regular expression retrieved from:
# http://www.regular-expressions.info/email.html # http://www.regular-expressions.info/email.html
IS_EMAIL_RE = re.compile( IS_EMAIL_RE = re.compile(
r"(?P<userid>[a-z0-9!#$%&'*+/=?^_`{|}~-]+" r"(?P<userid>[a-z0-9$%+=_~-]+"
r"(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)" r"(?:\.[a-z0-9$%+=_~-]+)"
r"*)@(?P<domain>(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+" r"*)@(?P<domain>(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+"
r"[a-z0-9](?:[a-z0-9-]*" r"[a-z0-9](?:[a-z0-9-]*"
r"[a-z0-9]))?", r"[a-z0-9]))?",
@ -312,6 +313,14 @@ class NotifyBase(object):
""" """
return IS_EMAIL_RE.match(address) is not None return IS_EMAIL_RE.match(address) is not None
@staticmethod
def is_hostname(hostname):
"""
Returns True if specified entry is a hostname
"""
return is_hostname(hostname)
@staticmethod @staticmethod
def parse_url(url): def parse_url(url):
""" """

View File

@ -19,13 +19,11 @@
import re import re
from datetime import datetime from datetime import datetime
from smtplib import SMTP import smtplib
from smtplib import SMTPException
from socket import error as SocketError from socket import error as SocketError
from email.mime.text import MIMEText from email.mime.text import MIMEText
from ..utils import compat_is_basestring
from .NotifyBase import NotifyBase from .NotifyBase import NotifyBase
from .NotifyBase import NotifyFormat from .NotifyBase import NotifyFormat
@ -49,7 +47,7 @@ WEBBASE_LOOKUP_TABLE = (
# Google GMail # Google GMail
( (
'Google Mail', 'Google Mail',
re.compile('^(?P<id>[^@]+)@(?P<domain>gmail\.com)$', re.I), re.compile(r'^(?P<id>[^@]+)@(?P<domain>gmail\.com)$', re.I),
{ {
'port': 587, 'port': 587,
'smtp_host': 'smtp.gmail.com', 'smtp_host': 'smtp.gmail.com',
@ -61,7 +59,7 @@ WEBBASE_LOOKUP_TABLE = (
# Pronto Mail # Pronto Mail
( (
'Pronto Mail', 'Pronto Mail',
re.compile('^(?P<id>[^@]+)@(?P<domain>prontomail\.com)$', re.I), re.compile(r'^(?P<id>[^@]+)@(?P<domain>prontomail\.com)$', re.I),
{ {
'port': 465, 'port': 465,
'smtp_host': 'secure.emailsrvr.com', 'smtp_host': 'secure.emailsrvr.com',
@ -73,7 +71,7 @@ WEBBASE_LOOKUP_TABLE = (
# Microsoft Hotmail # Microsoft Hotmail
( (
'Microsoft Hotmail', 'Microsoft Hotmail',
re.compile('^(?P<id>[^@]+)@(?P<domain>(hotmail|live)\.com)$', re.I), re.compile(r'^(?P<id>[^@]+)@(?P<domain>(hotmail|live)\.com)$', re.I),
{ {
'port': 587, 'port': 587,
'smtp_host': 'smtp.live.com', 'smtp_host': 'smtp.live.com',
@ -85,7 +83,7 @@ WEBBASE_LOOKUP_TABLE = (
# Yahoo Mail # Yahoo Mail
( (
'Yahoo Mail', 'Yahoo Mail',
re.compile('^(?P<id>[^@]+)@(?P<domain>yahoo\.(ca|com))$', re.I), re.compile(r'^(?P<id>[^@]+)@(?P<domain>yahoo\.(ca|com))$', re.I),
{ {
'port': 465, 'port': 465,
'smtp_host': 'smtp.mail.yahoo.com', 'smtp_host': 'smtp.mail.yahoo.com',
@ -97,7 +95,7 @@ WEBBASE_LOOKUP_TABLE = (
# Catch All # Catch All
( (
'Custom', 'Custom',
re.compile('^(?P<id>[^@]+)@(?P<domain>.+)$', re.I), re.compile(r'^(?P<id>[^@]+)@(?P<domain>.+)$', re.I),
{ {
# Setting smtp_host to None is a way of # Setting smtp_host to None is a way of
# auto-detecting it based on other parameters # auto-detecting it based on other parameters
@ -159,28 +157,19 @@ class NotifyEmail(NotifyBase):
# Now we want to construct the To and From email # Now we want to construct the To and From email
# addresses from the URL provided # addresses from the URL provided
self.from_name = kwargs.get('name', 'NZB Notification') self.from_name = kwargs.get('name', NotifyBase.app_desc)
self.from_addr = kwargs.get('from', None) self.from_addr = kwargs.get('from', None)
if not self.from_addr:
# Keep trying to be clever and make it equal to the to address
self.from_addr = self.to_addr
if not compat_is_basestring(self.to_addr):
raise TypeError('No valid ~To~ email address specified.')
if not NotifyBase.is_email(self.to_addr): if not NotifyBase.is_email(self.to_addr):
raise TypeError('Invalid ~To~ email format: %s' % self.to_addr) raise TypeError('Invalid ~To~ email format: %s' % self.to_addr)
if not compat_is_basestring(self.from_addr):
raise TypeError('No valid ~From~ email address specified.')
match = NotifyBase.is_email(self.from_addr) match = NotifyBase.is_email(self.from_addr)
if not match: if not match:
# Parse Source domain based on from_addr # Parse Source domain based on from_addr
raise TypeError('Invalid ~From~ email format: %s' % self.to_addr) raise TypeError('Invalid ~From~ email format: %s' % self.to_addr)
# Now detect the SMTP Server # Now detect the SMTP Server
self.smtp_host = kwargs.get('smtp_host', None) self.smtp_host = kwargs.get('smtp_host', '')
# Apply any defaults based on certain known configurations # Apply any defaults based on certain known configurations
self.NotifyEmailDefaults() self.NotifyEmailDefaults()
@ -269,7 +258,7 @@ class NotifyEmail(NotifyBase):
try: try:
self.logger.debug('Connecting to remote SMTP server...') self.logger.debug('Connecting to remote SMTP server...')
socket = SMTP( socket = smtplib.SMTP(
self.smtp_host, self.smtp_host,
self.port, self.port,
None, None,
@ -293,7 +282,7 @@ class NotifyEmail(NotifyBase):
self.to_addr, self.to_addr,
)) ))
except (SocketError, SMTPException) as e: except (SocketError, smtplib.SMTPException, RuntimeError) as e:
self.logger.warning( self.logger.warning(
'A Connection error occured sending Email ' 'A Connection error occured sending Email '
'notification to %s.' % self.smtp_host) 'notification to %s.' % self.smtp_host)
@ -334,88 +323,52 @@ class NotifyEmail(NotifyBase):
if 'format' in results['qsd'] and len(results['qsd']['format']): if 'format' in results['qsd'] and len(results['qsd']['format']):
# Extract email format (Text/Html) # Extract email format (Text/Html)
try:
format = NotifyBase.unquote(results['qsd']['format']).lower() format = NotifyBase.unquote(results['qsd']['format']).lower()
if len(format) > 0 and format[0] == 't': if len(format) > 0 and format[0] == 't':
results['notify_format'] = NotifyFormat.TEXT results['notify_format'] = NotifyFormat.TEXT
except AttributeError: if 'to' in results['qsd'] and len(results['qsd']['to']):
pass to_addr = NotifyBase.unquote(results['qsd']['to']).strip()
else:
# get 'To' email address # get 'To' email address
try: try:
to_addr = filter(bool, NotifyBase.split_path(results['host']))[0] to_addr = '%s@%s' % (
re.split(
'[\s@]+', NotifyBase.unquote(results['user']))[0],
results.get('host', '')
)
except (AttributeError, IndexError): except (AttributeError, IndexError):
# No problem, we have other ways of getting # No problem, we have other ways of getting
# the To address # the To address
pass pass
if not NotifyBase.is_email(to_addr):
if results['user']:
# Try to be clever and build a potential
# email address based on what we've been provided
to_addr = '%s@%s' % (
re.split('[\s@]+', results['user'])[0],
re.split('[\s@]+', to_addr)[-1],
)
if not NotifyBase.is_email(to_addr):
NotifyBase.logger.error(
'%s does not contain a recipient email.' %
NotifyBase.unquote(results['url'].lstrip('/')),
)
return None
# Attempt to detect 'from' email address # Attempt to detect 'from' email address
from_addr = to_addr from_addr = to_addr
try:
if 'from' in results['qsd'] and len(results['qsd']['from']): if 'from' in results['qsd'] and len(results['qsd']['from']):
from_addr = results['qsd']['from'] from_addr = NotifyBase.unquote(results['qsd']['from'])
if not NotifyBase.is_email(results['qsd']['from']): if not NotifyBase.is_email(from_addr):
# Lets be clever and attempt to make the from # Lets be clever and attempt to make the from
# address email # address an email based on the to address
from_addr = '%s@%s' % ( from_addr = '%s@%s' % (
re.split('[\s@]+', from_addr)[0], re.split('[\s@]+', from_addr)[0],
re.split('[\s@]+', to_addr)[-1], re.split('[\s@]+', to_addr)[-1],
) )
if not NotifyBase.is_email(from_addr):
NotifyBase.logger.error(
'%s does not contain a from address.' %
NotifyBase.unquote(results['url'].lstrip('/')),
)
return None
except AttributeError:
pass
try:
if 'name' in results['qsd'] and len(results['qsd']['name']): if 'name' in results['qsd'] and len(results['qsd']['name']):
# Extract from name to associate with from address # Extract from name to associate with from address
results['name'] = NotifyBase.unquote(results['qsd']['name']) results['name'] = NotifyBase.unquote(results['qsd']['name'])
except AttributeError:
pass
try:
if 'timeout' in results['qsd'] and len(results['qsd']['timeout']): if 'timeout' in results['qsd'] and len(results['qsd']['timeout']):
# Extract the timeout to associate with smtp server # Extract the timeout to associate with smtp server
results['timeout'] = NotifyBase.unquote( results['timeout'] = results['qsd']['timeout']
results['qsd']['timeout'])
except AttributeError:
pass
# Store SMTP Host if specified # Store SMTP Host if specified
try:
# Extract from password to associate with smtp server
if 'smtp' in results['qsd'] and len(results['qsd']['smtp']): if 'smtp' in results['qsd'] and len(results['qsd']['smtp']):
# Extract the smtp server
smtp_host = NotifyBase.unquote(results['qsd']['smtp']) smtp_host = NotifyBase.unquote(results['qsd']['smtp'])
except AttributeError:
pass
results['to'] = to_addr results['to'] = to_addr
results['from'] = from_addr results['from'] = from_addr
results['smtp_host'] = smtp_host results['smtp_host'] = smtp_host

View File

@ -16,6 +16,10 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU Lesser General Public License for more details.
# Used for Testing; specifically test_email_plugin.py needs access
# to the modules WEBBASE_LOOKUP_TABLE and WebBaseLogin objects
from . import NotifyEmail as NotifyEmailBase
from .NotifyBoxcar import NotifyBoxcar from .NotifyBoxcar import NotifyBoxcar
from .NotifyEmail import NotifyEmail from .NotifyEmail import NotifyEmail
from .NotifyFaast import NotifyFaast from .NotifyFaast import NotifyFaast
@ -52,4 +56,7 @@ __all__ = [
# Reference # Reference
'NotifyImageSize', 'NOTIFY_IMAGE_SIZES', 'NotifyType', 'NOTIFY_TYPES', 'NotifyImageSize', 'NOTIFY_IMAGE_SIZES', 'NotifyType', 'NOTIFY_TYPES',
# NotifyEmail Base References (used for Testing)
'NotifyEmailBase',
] ]

View File

@ -85,6 +85,20 @@ TIDY_NUX_TRIM_RE = re.compile(
) )
def is_hostname(hostname):
"""
Validate hostname
"""
if len(hostname) > 255 or len(hostname) == 0:
return False
if hostname[-1] == ".":
hostname = hostname[:-1]
allowed = re.compile("(?!-)[A-Z\d_-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split("."))
def compat_is_basestring(content): def compat_is_basestring(content):
""" """
Python 3 support for checking if content is unicode and/or Python 3 support for checking if content is unicode and/or
@ -279,6 +293,10 @@ def parse_url(url, default_schema='http'):
if result['port'] == 0: if result['port'] == 0:
result['port'] = None result['port'] = None
if not is_hostname(result['host']):
# Nothing more we can do without a hostname
return None
# Re-assemble cleaned up version of the url # Re-assemble cleaned up version of the url
result['url'] = '%s://' % result['schema'] result['url'] = '%s://' % result['schema']
if compat_is_basestring(result['user']): if compat_is_basestring(result['user']):

302
test/test_email_plugin.py Normal file
View File

@ -0,0 +1,302 @@
# -*- coding: utf-8 -*-
#
# NotifyEmail - Unit Tests
#
# Copyright (C) 2017 Chris Caron <lead2gold@gmail.com>
#
# 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 smtplib
import mock
import re
VALID_URLS = (
##################################
# NotifyEmail
##################################
('mailto://', {
'instance': None,
}),
('mailtos://', {
'instance': None,
}),
('mailto://:@/', {
'instance': None
}),
# No Username
('mailtos://:pass@nuxref.com:567', {
# Can't prepare a To address using this expression
'exception': TypeError,
}),
# Pre-Configured Email Services
('mailto://user:pass@gmail.com', {
'instance': plugins.NotifyEmail,
}),
('mailto://user:pass@hotmail.com', {
'instance': plugins.NotifyEmail,
}),
('mailto://user:pass@live.com', {
'instance': plugins.NotifyEmail,
}),
('mailto://user:pass@prontomail.com', {
'instance': plugins.NotifyEmail,
}),
('mailto://user:pass@yahoo.com', {
'instance': plugins.NotifyEmail,
}),
('mailto://user:pass@yahoo.ca', {
'instance': plugins.NotifyEmail,
}),
# Custom Emails
('mailtos://user:pass@nuxref.com:567', {
'instance': plugins.NotifyEmail,
}),
('mailto://user:pass@nuxref.com:567?format=html', {
'instance': plugins.NotifyEmail,
}),
('mailtos://user:pass@nuxref.com:567?to=l2g@nuxref.com', {
'instance': plugins.NotifyEmail,
}),
(
'mailtos://user:pass@example.com?smtp=smtp.example.com&timeout=5'
'&name=l2g&from=noreply@example.com', {
'instance': plugins.NotifyEmail,
},
),
('mailto://user:pass@example.com?timeout=invalid.entry', {
'instance': plugins.NotifyEmail,
}),
('mailto://user:pass@example.com?timeout=invalid.entry', {
'instance': plugins.NotifyEmail,
}),
(
'mailto://user:pass@example.com:2525?user=l2g@example.com'
'&pass=l2g@apprise!is!Awesome', {
'instance': plugins.NotifyEmail,
},
),
(
'mailto://user:pass@example.com:2525?user=l2g@example.com'
'&pass=l2g@apprise!is!Awesome&format=text', {
'instance': plugins.NotifyEmail,
},
),
# No Password
('mailtos://user:@nuxref.com', {
'instance': plugins.NotifyEmail,
}),
# Invalid From Address (falls back to using To Address)
('mailtos://user:pass@nuxref.com?from=@', {
'exception': TypeError,
}),
# Invalid To Address
('mailtos://nuxref.com?user=&pass=.', {
'exception': TypeError,
}),
# Valid URL, but can't structure a proper email
('mailtos://nuxref.com?user=%20!&pass=.', {
'exception': TypeError,
}),
# Invalid To Address
('mailtos://nuxref.com?to=test', {
'exception': TypeError,
}),
# Can make a To address using what we have (l2g@nuxref.com)
('mailtos://nuxref.com?user=l2g&pass=.', {
'instance': plugins.NotifyEmail,
}),
('mailto://user:pass@localhost:2525', {
'instance': plugins.NotifyEmail,
# Throws a series of connection and transfer exceptions when this flag
# is set and tests that we gracfully handle them
'test_smtplib_exceptions': True,
}),
)
@mock.patch('smtplib.SMTP')
def test_email_plugin(mock_smtp):
"""
API: NotifyEmail Plugin()
"""
# 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
smtplib_response_code = meta.get(
'smtplib_response_code', 200 if response else 404)
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
if test_smtplib_exceptions is False:
pass
# Handle our default response
mock_socket.sendmail.return_value = smtplib_response_code
# mock_post.return_value.status_code = smtplib_response_code
# mock_get.return_value.status_code = smtplib_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_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',
'addr@example.com'),
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))
@mock.patch('smtplib.SMTP')
def test_webbase_lookup(mock_smtp):
"""
API: Web Based Lookup Tests
"""
from apprise.plugins import NotifyEmailBase
# 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://user:pass@l2g.com', suppress_exceptions=True)
assert(isinstance(obj, plugins.NotifyEmail))
assert obj.to_addr == 'user@l2g.com'
assert obj.from_addr == 'user@l2g.com'
assert obj.password == 'pass'
assert obj.user == 'user'
assert obj.secure is True
assert obj.port == 123
assert obj.smtp_host == 'smtp.l2g.com'

View File

@ -156,3 +156,11 @@ def test_notify_base_urls():
'https://user:pass@localhost?user=newuser') 'https://user:pass@localhost?user=newuser')
assert 'user' in results assert 'user' in results
assert results['user'] == "newuser" assert results['user'] == "newuser"
# Test invalid urls
assert NotifyBase.parse_url('https://:@/') is None
assert NotifyBase.parse_url('http://:@') is None
assert NotifyBase.parse_url('http://@') is None
assert NotifyBase.parse_url('http:///') is None
assert NotifyBase.parse_url('http://:test/') is None
assert NotifyBase.parse_url('http://pass:test/') is None

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# NotifyJSON Unit Tests # REST Based Plugins - Unit Tests
# #
# Copyright (C) 2017 Chris Caron <lead2gold@gmail.com> # Copyright (C) 2017 Chris Caron <lead2gold@gmail.com>
# #
@ -57,6 +57,9 @@ VALID_URLS = (
('jsons://user:pass@localhost:8080', { ('jsons://user:pass@localhost:8080', {
'instance': plugins.NotifyJSON, 'instance': plugins.NotifyJSON,
}), }),
('json://:@/', {
'instance': None,
}),
('json://user:pass@localhost:8081', { ('json://user:pass@localhost:8081', {
'instance': plugins.NotifyJSON, 'instance': plugins.NotifyJSON,
# force a failure # force a failure
@ -113,6 +116,9 @@ VALID_URLS = (
# Thrown because the webhook is not in a valid format # Thrown because the webhook is not in a valid format
'exception': TypeError, 'exception': TypeError,
}), }),
('mmost://:@/', {
'instance': None,
}),
('mmost://localhost/3ccdd113474722377935511fc85d3dd4', { ('mmost://localhost/3ccdd113474722377935511fc85d3dd4', {
'instance': plugins.NotifyMatterMost, 'instance': plugins.NotifyMatterMost,
# force a failure # force a failure
@ -136,9 +142,9 @@ VALID_URLS = (
@mock.patch('requests.get') @mock.patch('requests.get')
@mock.patch('requests.post') @mock.patch('requests.post')
def test_plugins(mock_post, mock_get): def test_rest_plugins(mock_post, mock_get):
""" """
API: Plugins() object API: REST Based Plugins()
""" """
@ -199,6 +205,11 @@ def test_plugins(mock_post, mock_get):
# We're done # We're done
continue 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)) assert(isinstance(obj, instance))
if self: if self:
@ -210,7 +221,7 @@ def test_plugins(mock_post, mock_get):
try: try:
if test_requests_exceptions is False: if test_requests_exceptions is False:
# check tht we're as expected # check that we're as expected
assert obj.notify( assert obj.notify(
title='test', body='body', title='test', body='body',
notify_type=NotifyType.INFO) == response notify_type=NotifyType.INFO) == response
@ -230,10 +241,12 @@ def test_plugins(mock_post, mock_get):
except Exception as e: except Exception as e:
# We can't handle this exception type # We can't handle this exception type
print('%s / %s' % (url, str(e)))
assert False assert False
except AssertionError: except AssertionError:
# Don't mess with these entries # Don't mess with these entries
print('%s AssertionError' % url)
raise raise
except Exception as e: except Exception as e:
@ -242,9 +255,11 @@ def test_plugins(mock_post, mock_get):
except AssertionError: except AssertionError:
# Don't mess with these entries # Don't mess with these entries
print('%s / %s' % (url, str(e)))
raise raise
except Exception as e: except Exception as e:
# Handle our exception # Handle our exception
print('%s / %s' % (url, str(e)))
assert(exception is not None) assert(exception is not None)
assert(isinstance(e, exception)) assert(isinstance(e, exception))

View File

@ -264,6 +264,24 @@ def test_parse_bool():
assert(utils.parse_bool('OhYeah', True) is True) assert(utils.parse_bool('OhYeah', True) is True)
def test_is_hostname():
"""
API: is_hostname() function
"""
# Valid Hostnames
assert utils.is_hostname('yahoo.ca') is True
assert utils.is_hostname('yahoo.ca.') is True
assert utils.is_hostname('valid-dashes-in-host.ca') is True
assert utils.is_hostname('valid-underscores_in_host.ca') is True
# Invalid Hostnames
assert utils.is_hostname('invalid-characters_#^.ca') is False
assert utils.is_hostname(' spaces ') is False
assert utils.is_hostname(' ') is False
assert utils.is_hostname('') is False
def test_parse_list(): def test_parse_list():
"utils: parse_list() testing """ "utils: parse_list() testing """