mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Add more providers, bump yessssms version to 0.4.1 (#26874)
* 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 🐈
This commit is contained in:
parent
2dfdc5f6f8
commit
f9ac204cc5
3
homeassistant/components/yessssms/const.py
Normal file
3
homeassistant/components/yessssms/const.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
"""Const for YesssSMS."""
|
||||||
|
|
||||||
|
CONF_PROVIDER = "provider"
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Yessssms",
|
"name": "Yessssms",
|
||||||
"documentation": "https://www.home-assistant.io/components/yessssms",
|
"documentation": "https://www.home-assistant.io/components/yessssms",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"YesssSMS==0.2.3"
|
"YesssSMS==0.4.1"
|
||||||
],
|
],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
|
@ -3,11 +3,16 @@ import logging
|
|||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from YesssSMS import YesssSMS
|
||||||
|
|
||||||
from homeassistant.const import CONF_PASSWORD, CONF_RECIPIENT, CONF_USERNAME
|
from homeassistant.const import CONF_PASSWORD, CONF_RECIPIENT, CONF_USERNAME
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
from homeassistant.components.notify import PLATFORM_SCHEMA, BaseNotificationService
|
from homeassistant.components.notify import PLATFORM_SCHEMA, BaseNotificationService
|
||||||
|
|
||||||
|
|
||||||
|
from .const import CONF_PROVIDER
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
@ -15,27 +20,52 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|||||||
vol.Required(CONF_USERNAME): cv.string,
|
vol.Required(CONF_USERNAME): cv.string,
|
||||||
vol.Required(CONF_PASSWORD): cv.string,
|
vol.Required(CONF_PASSWORD): cv.string,
|
||||||
vol.Required(CONF_RECIPIENT): cv.string,
|
vol.Required(CONF_RECIPIENT): cv.string,
|
||||||
|
vol.Optional(CONF_PROVIDER, default="YESSS"): cv.string,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_service(hass, config, discovery_info=None):
|
def get_service(hass, config, discovery_info=None):
|
||||||
"""Get the YesssSMS notification service."""
|
"""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):
|
class YesssSMSNotificationService(BaseNotificationService):
|
||||||
"""Implement a notification service for the YesssSMS service."""
|
"""Implement a notification service for the YesssSMS service."""
|
||||||
|
|
||||||
def __init__(self, username, password, recipient):
|
def __init__(self, client, recipient):
|
||||||
"""Initialize the service."""
|
"""Initialize the service."""
|
||||||
from YesssSMS import YesssSMS
|
self.yesss = client
|
||||||
|
|
||||||
self.yesss = YesssSMS(username, password)
|
|
||||||
self._recipient = recipient
|
self._recipient = recipient
|
||||||
_LOGGER.debug("initialized; library version: %s", self.yesss.version())
|
|
||||||
|
|
||||||
def send_message(self, message="", **kwargs):
|
def send_message(self, message="", **kwargs):
|
||||||
"""Send a SMS message via Yesss.at's website."""
|
"""Send a SMS message via Yesss.at's website."""
|
||||||
@ -56,10 +86,12 @@ class YesssSMSNotificationService(BaseNotificationService):
|
|||||||
except self.yesss.EmptyMessageError as ex:
|
except self.yesss.EmptyMessageError as ex:
|
||||||
_LOGGER.error("Cannot send empty SMS message: %s", ex)
|
_LOGGER.error("Cannot send empty SMS message: %s", ex)
|
||||||
except self.yesss.SMSSendingError as ex:
|
except self.yesss.SMSSendingError as ex:
|
||||||
_LOGGER.error(str(ex), exc_info=ex)
|
_LOGGER.error(ex)
|
||||||
except ConnectionError as ex:
|
except self.yesss.ConnectionError as ex:
|
||||||
_LOGGER.error(
|
_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:
|
except self.yesss.AccountSuspendedError as ex:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
|
@ -100,7 +100,7 @@ TwitterAPI==2.5.9
|
|||||||
WazeRouteCalculator==0.10
|
WazeRouteCalculator==0.10
|
||||||
|
|
||||||
# homeassistant.components.yessssms
|
# homeassistant.components.yessssms
|
||||||
YesssSMS==0.2.3
|
YesssSMS==0.4.1
|
||||||
|
|
||||||
# homeassistant.components.abode
|
# homeassistant.components.abode
|
||||||
abodepy==0.15.0
|
abodepy==0.15.0
|
||||||
|
@ -37,7 +37,7 @@ PyRMVtransport==0.1.3
|
|||||||
PyTransportNSW==0.1.1
|
PyTransportNSW==0.1.1
|
||||||
|
|
||||||
# homeassistant.components.yessssms
|
# homeassistant.components.yessssms
|
||||||
YesssSMS==0.2.3
|
YesssSMS==0.4.1
|
||||||
|
|
||||||
# homeassistant.components.adguard
|
# homeassistant.components.adguard
|
||||||
adguardhome==0.2.1
|
adguardhome==0.2.1
|
||||||
|
@ -1,7 +1,148 @@
|
|||||||
"""The tests for the notify yessssms platform."""
|
"""The tests for the notify yessssms platform."""
|
||||||
import unittest
|
import unittest
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
import requests_mock
|
import requests_mock
|
||||||
|
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
import homeassistant.components.yessssms.notify as yessssms
|
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):
|
class TestNotifyYesssSMS(unittest.TestCase):
|
||||||
@ -12,7 +153,8 @@ class TestNotifyYesssSMS(unittest.TestCase):
|
|||||||
login = "06641234567"
|
login = "06641234567"
|
||||||
passwd = "testpasswd"
|
passwd = "testpasswd"
|
||||||
recipient = "06501234567"
|
recipient = "06501234567"
|
||||||
self.yessssms = yessssms.YesssSMSNotificationService(login, passwd, recipient)
|
client = yessssms.YesssSMS(login, passwd)
|
||||||
|
self.yessssms = yessssms.YesssSMSNotificationService(client, recipient)
|
||||||
|
|
||||||
@requests_mock.Mocker()
|
@requests_mock.Mocker()
|
||||||
def test_login_error(self, mock):
|
def test_login_error(self, mock):
|
||||||
@ -197,7 +339,7 @@ class TestNotifyYesssSMS(unittest.TestCase):
|
|||||||
"POST",
|
"POST",
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
self.yessssms.yesss._login_url,
|
self.yessssms.yesss._login_url,
|
||||||
exc=ConnectionError,
|
exc=yessssms.YesssSMS.ConnectionError,
|
||||||
)
|
)
|
||||||
|
|
||||||
message = "Testing YesssSMS platform :)"
|
message = "Testing YesssSMS platform :)"
|
||||||
@ -209,4 +351,4 @@ class TestNotifyYesssSMS(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertTrue(mock.called)
|
self.assertTrue(mock.called)
|
||||||
self.assertEqual(mock.call_count, 1)
|
self.assertEqual(mock.call_count, 1)
|
||||||
self.assertIn("unable to connect", context.output[0])
|
self.assertIn("cannot connect to provider", context.output[0])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user