YesssSMS handling more errors, upgrade to version 0.2.3 (#17052)

* YesssSMS handling more errors, upgrade to version 0.2.1

 - handling missing internet connection nicely
 - disabling login with non-working credentials (website locked account for 1 hour)
 - upgrade to new upstream version of YesssSMS

* notify.yessssms tests

* test requirements

* flake8 fix

* fixing tests, new upstream version 0.2.3

fixing tests based on requested changes, coverage

* removing unmotivated print

* passing exception to ConnectionError and SMSSendingError logger
This commit is contained in:
Florian Klien 2018-10-04 23:34:04 +02:00 committed by Adam Mills
parent b55c7a5ba2
commit ce1e8f8ace
6 changed files with 246 additions and 10 deletions

View file

@ -630,7 +630,6 @@ omit =
homeassistant/components/notify/telstra.py
homeassistant/components/notify/twitter.py
homeassistant/components/notify/xmpp.py
homeassistant/components/notify/yessssms.py
homeassistant/components/nuimo_controller.py
homeassistant/components/prometheus.py
homeassistant/components/rainbird.py

View file

@ -13,7 +13,8 @@ from homeassistant.components.notify import (
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD, CONF_RECIPIENT
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['YesssSMS==0.1.1b3']
REQUIREMENTS = ['YesssSMS==0.2.3']
_LOGGER = logging.getLogger(__name__)
@ -38,14 +39,38 @@ class YesssSMSNotificationService(BaseNotificationService):
from YesssSMS import YesssSMS
self.yesss = YesssSMS(username, password)
self._recipient = recipient
_LOGGER.debug(
"initialized; library version: %s", self.yesss.version())
def send_message(self, message="", **kwargs):
"""Send a SMS message via Yesss.at's website."""
if self.yesss.account_is_suspended():
# only retry to login after HASS was restarted with (hopefully)
# new login data.
_LOGGER.error(
"Account is suspended, cannot send SMS. "
"Check your login data and restart Home Assistant")
return
try:
self.yesss.send(self._recipient, message)
except ValueError as ex:
if str(ex).startswith("YesssSMS:"):
_LOGGER.error(str(ex))
except RuntimeError as ex:
if str(ex).startswith("YesssSMS:"):
_LOGGER.error(str(ex))
except self.yesss.NoRecipientError as ex:
_LOGGER.error(
"You need to provide a recipient for SMS notification: %s",
ex)
except self.yesss.EmptyMessageError as ex:
_LOGGER.error(
"Cannot send empty SMS message: %s", ex)
except self.yesss.SMSSendingError as ex:
_LOGGER.error(str(ex), exc_info=ex)
except ConnectionError as ex:
_LOGGER.error(
"YesssSMS: unable to connect to yesss.at server.",
exc_info=ex)
except self.yesss.AccountSuspendedError as ex:
_LOGGER.error(
"Wrong login credentials!! Verify correct credentials and "
"restart Home Assistant: %s", ex)
except self.yesss.LoginError as ex:
_LOGGER.error("Wrong login credentials: %s", ex)
else:
_LOGGER.info("SMS sent")

View file

@ -76,7 +76,7 @@ TwitterAPI==2.5.4
WazeRouteCalculator==0.6
# homeassistant.components.notify.yessssms
YesssSMS==0.1.1b3
YesssSMS==0.2.3
# homeassistant.components.abode
abodepy==0.13.1

View file

@ -24,6 +24,9 @@ HAP-python==2.2.2
# homeassistant.components.sensor.rmvtransport
PyRMVtransport==0.1
# homeassistant.components.notify.yessssms
YesssSMS==0.2.3
# homeassistant.components.device_tracker.automatic
aioautomatic==0.6.5

View file

@ -104,7 +104,8 @@ TEST_REQUIREMENTS = (
'yahoo-finance',
'pythonwhois',
'wakeonlan',
'vultr'
'vultr',
'YesssSMS',
)
IGNORE_PACKAGES = (

View file

@ -0,0 +1,208 @@
"""The tests for the notify yessssms platform."""
import unittest
import requests_mock
from homeassistant.components.notify import yessssms
class TestNotifyYesssSMS(unittest.TestCase):
"""Test the yessssms notify."""
def setUp(self): # pylint: disable=invalid-name
"""Set up things to be run when tests are started."""
login = "06641234567"
passwd = "testpasswd"
recipient = "06501234567"
self.yessssms = yessssms.YesssSMSNotificationService(
login, passwd, recipient)
@requests_mock.Mocker()
def test_login_error(self, mock):
"""Test login that fails."""
mock.register_uri(
requests_mock.POST,
# pylint: disable=protected-access
self.yessssms.yesss._login_url,
status_code=200,
text="BlaBlaBla<strong>Login nicht erfolgreichBlaBla"
)
message = "Testing YesssSMS platform :)"
with self.assertLogs("homeassistant.components.notify",
level='ERROR'):
self.yessssms.send_message(message)
self.assertTrue(mock.called)
self.assertEqual(mock.call_count, 1)
def test_empty_message_error(self):
"""Test for an empty SMS message error."""
message = ""
with self.assertLogs("homeassistant.components.notify",
level='ERROR'):
self.yessssms.send_message(message)
@requests_mock.Mocker()
def test_error_account_suspended(self, mock):
"""Test login that fails after multiple attempts."""
mock.register_uri(
'POST',
# pylint: disable=protected-access
self.yessssms.yesss._login_url,
status_code=200,
text="BlaBlaBla<strong>Login nicht erfolgreichBlaBla"
)
message = "Testing YesssSMS platform :)"
with self.assertLogs("homeassistant.components.notify",
level='ERROR'):
self.yessssms.send_message(message)
self.assertTrue(mock.called)
self.assertEqual(mock.call_count, 1)
mock.register_uri(
'POST',
# pylint: disable=protected-access
self.yessssms.yesss._login_url,
status_code=200,
text="Wegen 3 ungültigen Login-Versuchen ist Ihr Account für "
"eine Stunde gesperrt."
)
message = "Testing YesssSMS platform :)"
with self.assertLogs("homeassistant.components.notify",
level='ERROR'):
self.yessssms.send_message(message)
self.assertTrue(mock.called)
self.assertEqual(mock.call_count, 2)
def test_error_account_suspended_2(self):
"""Test login that fails after multiple attempts."""
message = "Testing YesssSMS platform :)"
# pylint: disable=protected-access
self.yessssms.yesss._suspended = True
with self.assertLogs("homeassistant.components.notify",
level='ERROR') as context:
self.yessssms.send_message(message)
self.assertIn("Account is suspended, cannot send SMS.",
context.output[0])
@requests_mock.Mocker()
def test_send_message(self, mock):
"""Test send message."""
message = "Testing YesssSMS platform :)"
mock.register_uri(
'POST',
# pylint: disable=protected-access
self.yessssms.yesss._login_url,
status_code=302,
# pylint: disable=protected-access
headers={'location': self.yessssms.yesss._kontomanager}
)
# pylint: disable=protected-access
login = self.yessssms.yesss._logindata['login_rufnummer']
mock.register_uri(
'GET',
# pylint: disable=protected-access
self.yessssms.yesss._kontomanager,
status_code=200,
text="test..." + login + "</a>"
)
mock.register_uri(
'POST',
# pylint: disable=protected-access
self.yessssms.yesss._websms_url,
status_code=200,
text="<h1>Ihre SMS wurde erfolgreich verschickt!</h1>"
)
mock.register_uri(
'GET',
# pylint: disable=protected-access
self.yessssms.yesss._logout_url,
status_code=200,
)
with self.assertLogs("homeassistant.components.notify",
level='INFO') as context:
self.yessssms.send_message(message)
self.assertIn("SMS sent", context.output[0])
self.assertTrue(mock.called)
self.assertEqual(mock.call_count, 4)
self.assertIn(mock.last_request.scheme + "://" +
mock.last_request.hostname +
mock.last_request.path + "?" +
mock.last_request.query,
# pylint: disable=protected-access
self.yessssms.yesss._logout_url)
def test_no_recipient_error(self):
"""Test for missing/empty recipient."""
message = "Testing YesssSMS platform :)"
# pylint: disable=protected-access
self.yessssms._recipient = ""
with self.assertLogs("homeassistant.components.notify",
level='ERROR') as context:
self.yessssms.send_message(message)
self.assertIn("You need to provide a recipient for SMS notification",
context.output[0])
@requests_mock.Mocker()
def test_sms_sending_error(self, mock):
"""Test sms sending error."""
mock.register_uri(
'POST',
# pylint: disable=protected-access
self.yessssms.yesss._login_url,
status_code=302,
# pylint: disable=protected-access
headers={'location': self.yessssms.yesss._kontomanager}
)
# pylint: disable=protected-access
login = self.yessssms.yesss._logindata['login_rufnummer']
mock.register_uri(
'GET',
# pylint: disable=protected-access
self.yessssms.yesss._kontomanager,
status_code=200,
text="test..." + login + "</a>"
)
mock.register_uri(
'POST',
# pylint: disable=protected-access
self.yessssms.yesss._websms_url,
status_code=500
)
message = "Testing YesssSMS platform :)"
with self.assertLogs("homeassistant.components.notify",
level='ERROR') as context:
self.yessssms.send_message(message)
self.assertTrue(mock.called)
self.assertEqual(mock.call_count, 3)
self.assertIn("YesssSMS: error sending SMS", context.output[0])
@requests_mock.Mocker()
def test_connection_error(self, mock):
"""Test connection error."""
mock.register_uri(
'POST',
# pylint: disable=protected-access
self.yessssms.yesss._login_url,
exc=ConnectionError
)
message = "Testing YesssSMS platform :)"
with self.assertLogs("homeassistant.components.notify",
level='ERROR') as context:
self.yessssms.send_message(message)
self.assertTrue(mock.called)
self.assertEqual(mock.call_count, 1)
self.assertIn("unable to connect", context.output[0])