Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -621,8 +621,6 @@ omit =
homeassistant/components/shodan/sensor.py
homeassistant/components/sht31/sensor.py
homeassistant/components/sigfox/sensor.py
homeassistant/components/signal_messenger/__init__.py
homeassistant/components/signal_messenger/notify.py
homeassistant/components/simplepush/notify.py
homeassistant/components/simplisafe/__init__.py
homeassistant/components/simplisafe/alarm_control_panel.py
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/signal_messenger/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"documentation": "https://www.home-assistant.io/integrations/signal_messenger",
"dependencies": [],
"codeowners": ["@bbernhard"],
"requirements": ["pysignalclirestapi==0.1.4"]
"requirements": ["pysignalclirestapi==0.2.4"]
}
22 changes: 15 additions & 7 deletions homeassistant/components/signal_messenger/notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
CONF_RECP_NR = "recipients"
CONF_SIGNAL_CLI_REST_API = "url"
ATTR_FILENAME = "attachment"
ATTR_FILENAMES = "attachments"

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
Expand All @@ -34,9 +35,7 @@ def get_service(hass, config, discovery_info=None):
recp_nrs = config[CONF_RECP_NR]
signal_cli_rest_api_url = config[CONF_SIGNAL_CLI_REST_API]

signal_cli_rest_api = SignalCliRestApi(
signal_cli_rest_api_url, sender_nr, api_version=1
)
signal_cli_rest_api = SignalCliRestApi(signal_cli_rest_api_url, sender_nr)

return SignalNotificationService(recp_nrs, signal_cli_rest_api)

Expand All @@ -60,12 +59,21 @@ def send_message(self, message="", **kwargs):

data = kwargs.get(ATTR_DATA)

filename = None
if data is not None and ATTR_FILENAME in data:
filename = data[ATTR_FILENAME]
filenames = None
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer that we avoid the breaking change unnecessarily here.

This could be done by allowing both the attribute filename as well as the attribute filenames to be provided and then internally adding the filename to the list of filenames.

Copy link
Copy Markdown
Contributor Author

@bbernhard bbernhard Jan 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me 👍 I'll adapt the PR, thanks!

Should the attachment option also be mentioned in the documentation then, or would you see that primarily as a way to stay backwards compatible and as something that's not worth mentioning in the documentation?

Copy link
Copy Markdown
Member

@rohankapoorcom rohankapoorcom Jan 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would mark it as deprecated and log a warning that it's deprecated and will be removed in version x.y.z (pick a version that's like 3 versions out).

If you are using vol to validate the schema of the service call, we have the deprecated validation helper in config_validation

Alternatively we could keep using attachment as the key and accept both a singular string or a list of strings.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for your suggestions, very much appreciated!

I've updated the PR, please let me know if there's anything else that needs to be changed.

(I've also removed the Breaking changes section from the PR description)

if data is not None:
if ATTR_FILENAMES in data:
filenames = data[ATTR_FILENAMES]
if ATTR_FILENAME in data:
_LOGGER.warning(
"The 'attachment' option is deprecated, please replace it with 'attachments'. This option will become invalid in version 0.108."
)
if filenames is None:
filenames = [data[ATTR_FILENAME]]
else:
filenames.append(data[ATTR_FILENAME])

try:
self._signal_cli_rest_api.send_message(message, self._recp_nrs, filename)
self._signal_cli_rest_api.send_message(message, self._recp_nrs, filenames)
except SignalCliRestApiError as ex:
_LOGGER.error("%s", ex)
raise ex
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1491,7 +1491,7 @@ pysesame2==1.0.1
pysher==1.0.1

# homeassistant.components.signal_messenger
pysignalclirestapi==0.1.4
pysignalclirestapi==0.2.4

# homeassistant.components.sma
pysma==0.3.5
Expand Down
3 changes: 3 additions & 0 deletions requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,9 @@ pyps4-2ndscreen==1.0.6
# homeassistant.components.qwikswitch
pyqwikswitch==0.93

# homeassistant.components.signal_messenger
pysignalclirestapi==0.2.4

# homeassistant.components.sma
pysma==0.3.5

Expand Down
1 change: 1 addition & 0 deletions requirements_test_pre_commit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

bandit==1.6.2
black==19.10b0
codespell==v1.16.0
flake8-docstrings==1.5.0
flake8==3.7.9
isort==v4.3.21
Expand Down
1 change: 1 addition & 0 deletions tests/components/signal_messenger/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests for the signal_messenger component."""
122 changes: 122 additions & 0 deletions tests/components/signal_messenger/test_notify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
"""The tests for the signal_messenger platform."""

import os
import tempfile
import unittest
from unittest.mock import patch

from pysignalclirestapi import SignalCliRestApi
import requests_mock

import homeassistant.components.signal_messenger.notify as signalmessenger
from homeassistant.setup import async_setup_component

BASE_COMPONENT = "notify"


async def test_signal_messenger_init(hass):
"""Test that service loads successfully."""

config = {
BASE_COMPONENT: {
"name": "test",
"platform": "signal_messenger",
"url": "http://127.0.0.1:8080",
"number": "+43443434343",
"recipients": ["+435565656565"],
}
}

with patch("pysignalclirestapi.SignalCliRestApi.send_message", return_value=None):
assert await async_setup_component(hass, BASE_COMPONENT, config)
await hass.async_block_till_done()

# Test that service loads successfully
assert hass.services.has_service(BASE_COMPONENT, "test")


class TestSignalMesssenger(unittest.TestCase):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New tests must be async standalone pytest test functions.

"""Test the signal_messenger notify."""

def setUp(self):
"""Set up things to be run when tests are started."""
recipients = ["+435565656565"]
number = "+43443434343"
client = SignalCliRestApi("http://127.0.0.1:8080", number)
self._signalmessenger = signalmessenger.SignalNotificationService(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should never set up a notify service or create an entity directly. We should always use the core to set up the component and platform. That will make the tests robust.

recipients, client
)

@requests_mock.Mocker()
def test_send_message(self, mock):
"""Test send message."""
message = "Testing Signal Messenger platform :)"
mock.register_uri(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to test the library requests. We should patch the library and make sure that we are interfacing with the library correctly.

The library is responsible for testing that it makes the correct requests.

"POST", "http://127.0.0.1:8080/v2/send", status_code=201,
)
mock.register_uri(
"GET",
"http://127.0.0.1:8080/v1/about",
status_code=200,
json={"versions": ["v1", "v2"]},
)
with self.assertLogs(
"homeassistant.components.signal_messenger.notify", level="DEBUG"
) as context:
self._signalmessenger.send_message(message)
self.assertIn("Sending signal message", context.output[0])
self.assertTrue(mock.called)
self.assertEqual(mock.call_count, 2)

@requests_mock.Mocker()
def test_send_message_should_show_deprecation_warning(self, mock):
"""Test send message."""
message = "Testing Signal Messenger platform with attachment :)"
mock.register_uri(
"POST", "http://127.0.0.1:8080/v2/send", status_code=201,
)
mock.register_uri(
"GET",
"http://127.0.0.1:8080/v1/about",
status_code=200,
json={"versions": ["v1", "v2"]},
)
with self.assertLogs(
"homeassistant.components.signal_messenger.notify", level="WARNING"
) as context:
with tempfile.NamedTemporaryFile(
suffix=".png", prefix=os.path.basename(__file__)
) as tf:
data = {"data": {"attachment": tf.name}}
self._signalmessenger.send_message(message, **data)
self.assertIn(
"The 'attachment' option is deprecated, please replace it with 'attachments'. This option will become invalid in version 0.108.",
context.output[0],
)
self.assertTrue(mock.called)
self.assertEqual(mock.call_count, 2)

@requests_mock.Mocker()
def test_send_message_with_attachment(self, mock):
"""Test send message."""
message = "Testing Signal Messenger platform :)"
mock.register_uri(
"POST", "http://127.0.0.1:8080/v2/send", status_code=201,
)
mock.register_uri(
"GET",
"http://127.0.0.1:8080/v1/about",
status_code=200,
json={"versions": ["v1", "v2"]},
)
with self.assertLogs(
"homeassistant.components.signal_messenger.notify", level="DEBUG"
) as context:
with tempfile.NamedTemporaryFile(
suffix=".png", prefix=os.path.basename(__file__)
) as tf:
data = {"data": {"attachments": [tf.name]}}
self._signalmessenger.send_message(message, **data)
self.assertIn("Sending signal message", context.output[0])
self.assertTrue(mock.called)
self.assertEqual(mock.call_count, 2)