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_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 # Apprise object can also be directly tested with 'if' keyword # No entries results in a False response assert not a # 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 # Apprise object can also be directly tested with 'if' keyword # At least one entry results in a True response assert a # 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 # Try adding nothing but delimiters assert a.add(',, ,, , , , ,') is False # The number of servers added doesn't change 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 '' @staticmethod def parse_url(url, *args, **kwargs): # always parseable return NotifyBase.parse_url(url, verify_host=False) class GoodNotification(NotifyBase): def __init__(self, **kwargs): super(GoodNotification, self).__init__( notify_format=NotifyFormat.HTML, **kwargs) def url(self): # Support URL return '' def send(self, **kwargs): # Pretend everything is okay return True @staticmethod def parse_url(url, *args, **kwargs): # always parseable return NotifyBase.parse_url(url, verify_host=False) # 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 # Send Attachment with success attach = join(TEST_VAR_DIR, 'apprise-test.gif') assert a.notify( body='body', title='test', notify_type=NotifyType.INFO, attach=attach) is True # Send the attachment as an AppriseAttachment object assert a.notify( body='body', title='test', notify_type=NotifyType.INFO, attach=AppriseAttachment(attach)) is True # test a invalid attachment assert a.notify( body='body', title='test', notify_type=NotifyType.INFO, attach='invalid://') is False # Repeat the same tests above... # however do it by directly accessing the object; this grants the similar # results: assert a[0].notify( body='body', title='test', notify_type=NotifyType.INFO, attach=attach) is True # Send the attachment as an AppriseAttachment object assert a[0].notify( body='body', title='test', notify_type=NotifyType.INFO, attach=AppriseAttachment(attach)) is True # test a invalid attachment assert a[0].notify( body='body', title='test', notify_type=NotifyType.INFO, attach='invalid://') is False # 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 # Test our socket details # rto = Socket Read Timeout # cto = Socket Connect Timeout plugin = a.instantiate('good://localhost?rto=5.1&cto=10') assert isinstance(plugin, NotifyBase) assert plugin.socket_connect_timeout == 10.0 assert plugin.socket_read_timeout == 5.1 plugin = a.instantiate('good://localhost?rto=invalid&cto=invalid') assert isinstance(plugin, NotifyBase) assert plugin.socket_connect_timeout == URLBase.socket_connect_timeout assert plugin.socket_read_timeout == URLBase.socket_read_timeout # 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() with pytest.raises(TypeError): a.instantiate('throw://localhost', suppress_exceptions=False) 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() with pytest.raises(TypeError): a.instantiate({ 'schema': 'throw', 'host': 'localhost'}, suppress_exceptions=False) assert len(a) == 0 assert a.instantiate({ 'schema': 'throw', 'host': 'localhost'}, suppress_exceptions=True) is None assert len(a) == 0