From 1aaee8265ecd0e0f5b23849a4683cf58aa22dce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Osb=C3=A4ck?= Date: Sun, 4 Jun 2017 16:06:25 +0200 Subject: [PATCH] Add support for the expirationTime parameter. Enabled by default in Chrome 60. Only accepts the param, doesn't act on the actual expiration date. Chrome will always pass NULL for now. https://github.com/w3c/push-api/pull/248 https://www.chromestatus.com/feature/4929396687241216 https://bugs.chromium.org/p/chromium/issues/detail?id=718837 --- homeassistant/components/notify/html5.py | 5 ++- tests/components/notify/test_html5.py | 46 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/notify/html5.py b/homeassistant/components/notify/html5.py index 495fc8a3c6f1af..c8ff6c7aa2fef8 100644 --- a/homeassistant/components/notify/html5.py +++ b/homeassistant/components/notify/html5.py @@ -48,6 +48,7 @@ ATTR_KEYS = 'keys' ATTR_AUTH = 'auth' ATTR_P256DH = 'p256dh' +ATTR_EXPIRATIONTIME = 'expirationTime' ATTR_TAG = 'tag' ATTR_ACTION = 'action' @@ -71,7 +72,9 @@ vol.Schema({ # pylint: disable=no-value-for-parameter vol.Required(ATTR_ENDPOINT): vol.Url(), - vol.Required(ATTR_KEYS): KEYS_SCHEMA + vol.Required(ATTR_KEYS): KEYS_SCHEMA, + vol.Optional(ATTR_EXPIRATIONTIME): + vol.Any(None, cv.positive_int) })) REGISTER_SCHEMA = vol.Schema({ diff --git a/tests/components/notify/test_html5.py b/tests/components/notify/test_html5.py index ff1076d1eeddf1..5aa8afb4f7df73 100644 --- a/tests/components/notify/test_html5.py +++ b/tests/components/notify/test_html5.py @@ -34,6 +34,14 @@ }, }, } +SUBSCRIPTION_4 = { + 'browser': 'chrome', + 'subscription': { + 'endpoint': 'https://google.com', + 'expirationTime': None, + 'keys': {'auth': 'auth', 'p256dh': 'p256dh'} + }, +} REGISTER_URL = '/api/notify.html5' PUBLISH_URL = '/api/notify.html5/callback' @@ -139,6 +147,44 @@ def test_registering_new_device_view(self, loop, test_client): handle = m() assert json.loads(handle.write.call_args[0][0]) == expected + @asyncio.coroutine + def test_registering_new_device_expiration_view(self, loop, test_client): + """Test that the HTML view works.""" + hass = MagicMock() + expected = { + 'unnamed device': SUBSCRIPTION_4, + } + + m = mock_open() + with patch( + 'homeassistant.components.notify.html5.open', m, create=True + ): + hass.config.path.return_value = 'file.conf' + service = html5.get_service(hass, {}) + + assert service is not None + + # assert hass.called + assert len(hass.mock_calls) == 3 + + view = hass.mock_calls[1][1][0] + assert view.json_path == hass.config.path.return_value + assert view.registrations == {} + + hass.loop = loop + app = mock_http_component_app(hass) + view.register(app.router) + client = yield from test_client(app) + hass.http.is_banned_ip.return_value = False + resp = yield from client.post(REGISTER_URL, + data=json.dumps(SUBSCRIPTION_4)) + + content = yield from resp.text() + assert resp.status == 200, content + assert view.registrations == expected + handle = m() + assert json.loads(handle.write.call_args[0][0]) == expected + @asyncio.coroutine def test_registering_new_device_validation(self, loop, test_client): """Test various errors when registering a new device."""