Add more providers, bump yessssms version to 0.4.1 ()

* bump yessssms version to 0.4.0

adds 'provider' config parameter
adds support for providers:

* billitel
* EDUCOM
* fenercell
* georg
* goood
* kronemobile
* kuriermobil
* SIMfonie
* teleplanet
* WOWWW
* yooopi

* black formatting

* moved CONF_PROVIDER to component

* black formatting

* moved error handling on init to get_service

* return None, init logging moved to get_service

* moved YesssSMS import to top of module

* test login data on init. add flag for login data test. removed KeyError

* catch connection error, remove CONF_TEST_LOGIN_DATA config flag

* requirements updated

* lint

* lint: use getters for protected members, bump version to 0.4.1b4

* requirements updated to 0.4.1b4

* fix logging messages, info to warning, clear up login_data check

* change valid login data message to debug

* fix tests

* add tests for get_service

* bump yessssms version 0.4.1

* tests for get_service refurbished

* test refactoring with fixtures

* polish fixtures 

* replace Mock with patch 🔄

* tiny string fixes, removed unused return_value 🐈
pull/27032/head^2
Florian Klien 2019-09-28 11:33:48 +02:00 committed by Martin Hjelmare
parent 2dfdc5f6f8
commit f9ac204cc5
6 changed files with 193 additions and 16 deletions

View File

@ -0,0 +1,3 @@
"""Const for YesssSMS."""
CONF_PROVIDER = "provider"

View File

@ -3,7 +3,7 @@
"name": "Yessssms",
"documentation": "https://www.home-assistant.io/components/yessssms",
"requirements": [
"YesssSMS==0.2.3"
"YesssSMS==0.4.1"
],
"dependencies": [],
"codeowners": [

View File

@ -3,11 +3,16 @@ import logging
import voluptuous as vol
from YesssSMS import YesssSMS
from homeassistant.const import CONF_PASSWORD, CONF_RECIPIENT, CONF_USERNAME
import homeassistant.helpers.config_validation as cv
from homeassistant.components.notify import PLATFORM_SCHEMA, BaseNotificationService
from .const import CONF_PROVIDER
_LOGGER = logging.getLogger(__name__)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
@ -15,27 +20,52 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_RECIPIENT): cv.string,
vol.Optional(CONF_PROVIDER, default="YESSS"): cv.string,
}
)
def get_service(hass, config, discovery_info=None):
"""Get the YesssSMS notification service."""
return YesssSMSNotificationService(
config[CONF_USERNAME], config[CONF_PASSWORD], config[CONF_RECIPIENT]
try:
yesss = YesssSMS(
config[CONF_USERNAME], config[CONF_PASSWORD], provider=config[CONF_PROVIDER]
)
except YesssSMS.UnsupportedProviderError as ex:
_LOGGER.error("Unknown provider: %s", ex)
return None
try:
if not yesss.login_data_valid():
_LOGGER.error(
"Login data is not valid! Please double check your login data at %s",
yesss.get_login_url(),
)
return None
_LOGGER.debug("Login data for '%s' valid", yesss.get_provider())
except YesssSMS.ConnectionError:
_LOGGER.warning(
"Connection Error, could not verify login data for '%s'",
yesss.get_provider(),
)
pass
_LOGGER.debug(
"initialized; library version: %s, with %s",
yesss.version(),
yesss.get_provider(),
)
return YesssSMSNotificationService(yesss, config[CONF_RECIPIENT])
class YesssSMSNotificationService(BaseNotificationService):
"""Implement a notification service for the YesssSMS service."""
def __init__(self, username, password, recipient):
def __init__(self, client, recipient):
"""Initialize the service."""
from YesssSMS import YesssSMS
self.yesss = YesssSMS(username, password)
self.yesss = client
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."""
@ -56,10 +86,12 @@ class YesssSMSNotificationService(BaseNotificationService):
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(ex)
except self.yesss.ConnectionError as ex:
_LOGGER.error(
"YesssSMS: unable to connect to yesss.at server.", exc_info=ex
"Unable to connect to server of provider (%s): %s",
self.yesss.get_provider(),
ex,
)
except self.yesss.AccountSuspendedError as ex:
_LOGGER.error(

View File

@ -100,7 +100,7 @@ TwitterAPI==2.5.9
WazeRouteCalculator==0.10
# homeassistant.components.yessssms
YesssSMS==0.2.3
YesssSMS==0.4.1
# homeassistant.components.abode
abodepy==0.15.0

View File

@ -37,7 +37,7 @@ PyRMVtransport==0.1.3
PyTransportNSW==0.1.1
# homeassistant.components.yessssms
YesssSMS==0.2.3
YesssSMS==0.4.1
# homeassistant.components.adguard
adguardhome==0.2.1

View File

@ -1,7 +1,148 @@
"""The tests for the notify yessssms platform."""
import unittest
from unittest.mock import patch
import pytest
import requests_mock
from homeassistant.setup import async_setup_component
import homeassistant.components.yessssms.notify as yessssms
from homeassistant.components.yessssms.const import CONF_PROVIDER
from homeassistant.const import CONF_PASSWORD, CONF_RECIPIENT, CONF_USERNAME
@pytest.fixture(name="config")
def config_data():
"""Set valid config data."""
config = {
"notify": {
"platform": "yessssms",
"name": "sms",
CONF_USERNAME: "06641234567",
CONF_PASSWORD: "secretPassword",
CONF_RECIPIENT: "06509876543",
CONF_PROVIDER: "educom",
}
}
return config
@pytest.fixture(name="valid_settings")
def init_valid_settings(hass, config):
"""Initialize component with valid settings."""
return async_setup_component(hass, "notify", config)
@pytest.fixture(name="invalid_provider_settings")
def init_invalid_provider_settings(hass, config):
"""Set invalid provider data and initalize component."""
config["notify"][CONF_PROVIDER] = "FantasyMobile" # invalid provider
return async_setup_component(hass, "notify", config)
@pytest.fixture(name="invalid_login_data")
def mock_invalid_login_data():
"""Mock invalid login data."""
path = "homeassistant.components.yessssms.notify.YesssSMS.login_data_valid"
with patch(path, return_value=False):
yield
@pytest.fixture(name="valid_login_data")
def mock_valid_login_data():
"""Mock valid login data."""
path = "homeassistant.components.yessssms.notify.YesssSMS.login_data_valid"
with patch(path, return_value=True):
yield
@pytest.fixture(name="connection_error")
def mock_connection_error():
"""Mock a connection error."""
path = "homeassistant.components.yessssms.notify.YesssSMS.login_data_valid"
with patch(path, side_effect=yessssms.YesssSMS.ConnectionError()):
yield
async def test_unsupported_provider_error(hass, caplog, invalid_provider_settings):
"""Test for error on unsupported provider."""
await invalid_provider_settings
for record in caplog.records:
if (
record.levelname == "ERROR"
and record.name == "homeassistant.components.yessssms.notify"
):
assert (
"Unknown provider: provider (fantasymobile) is not known to YesssSMS"
in record.message
)
assert (
"Unknown provider: provider (fantasymobile) is not known to YesssSMS"
in caplog.text
)
assert not hass.services.has_service("notify", "sms")
async def test_false_login_data_error(hass, caplog, valid_settings, invalid_login_data):
"""Test login data check error."""
await valid_settings
assert not hass.services.has_service("notify", "sms")
for record in caplog.records:
if (
record.levelname == "ERROR"
and record.name == "homeassistant.components.yessssms.notify"
):
assert (
"Login data is not valid! Please double check your login data at"
in record.message
)
async def test_init_success(hass, caplog, valid_settings, valid_login_data):
"""Test for successful init of yessssms."""
await valid_settings
assert hass.services.has_service("notify", "sms")
messages = []
for record in caplog.records:
if (
record.levelname == "DEBUG"
and record.name == "homeassistant.components.yessssms.notify"
):
messages.append(record.message)
assert "Login data for 'educom' valid" in messages[0]
assert (
"initialized; library version: {}".format(yessssms.YesssSMS("", "").version())
in messages[1]
)
async def test_connection_error_on_init(hass, caplog, valid_settings, connection_error):
"""Test for connection error on init."""
await valid_settings
assert hass.services.has_service("notify", "sms")
for record in caplog.records:
if (
record.levelname == "WARNING"
and record.name == "homeassistant.components.yessssms.notify"
):
assert (
"Connection Error, could not verify login data for '{}'".format(
"educom"
)
in record.message
)
for record in caplog.records:
if (
record.levelname == "DEBUG"
and record.name == "homeassistant.components.yessssms.notify"
):
assert (
"initialized; library version: {}".format(
yessssms.YesssSMS("", "").version()
)
in record.message
)
class TestNotifyYesssSMS(unittest.TestCase):
@ -12,7 +153,8 @@ class TestNotifyYesssSMS(unittest.TestCase):
login = "06641234567"
passwd = "testpasswd"
recipient = "06501234567"
self.yessssms = yessssms.YesssSMSNotificationService(login, passwd, recipient)
client = yessssms.YesssSMS(login, passwd)
self.yessssms = yessssms.YesssSMSNotificationService(client, recipient)
@requests_mock.Mocker()
def test_login_error(self, mock):
@ -197,7 +339,7 @@ class TestNotifyYesssSMS(unittest.TestCase):
"POST",
# pylint: disable=protected-access
self.yessssms.yesss._login_url,
exc=ConnectionError,
exc=yessssms.YesssSMS.ConnectionError,
)
message = "Testing YesssSMS platform :)"
@ -209,4 +351,4 @@ class TestNotifyYesssSMS(unittest.TestCase):
self.assertTrue(mock.called)
self.assertEqual(mock.call_count, 1)
self.assertIn("unable to connect", context.output[0])
self.assertIn("cannot connect to provider", context.output[0])