hass-core/tests/components/caldav/test_calendar.py
Penny Wood f195ecca4b Consolidate all platforms that have tests (#22109)
* Moved climate components with tests into platform dirs.

* Updated tests from climate component.

* Moved binary_sensor components with tests into platform dirs.

* Updated tests from binary_sensor component.

* Moved calendar components with tests into platform dirs.

* Updated tests from calendar component.

* Moved camera components with tests into platform dirs.

* Updated tests from camera component.

* Moved cover components with tests into platform dirs.

* Updated tests from cover component.

* Moved device_tracker components with tests into platform dirs.

* Updated tests from device_tracker component.

* Moved fan components with tests into platform dirs.

* Updated tests from fan component.

* Moved geo_location components with tests into platform dirs.

* Updated tests from geo_location component.

* Moved image_processing components with tests into platform dirs.

* Updated tests from image_processing component.

* Moved light components with tests into platform dirs.

* Updated tests from light component.

* Moved lock components with tests into platform dirs.

* Moved media_player components with tests into platform dirs.

* Updated tests from media_player component.

* Moved scene components with tests into platform dirs.

* Moved sensor components with tests into platform dirs.

* Updated tests from sensor component.

* Moved switch components with tests into platform dirs.

* Updated tests from sensor component.

* Moved vacuum components with tests into platform dirs.

* Updated tests from vacuum component.

* Moved weather components with tests into platform dirs.

* Fixed __init__.py files

* Fixes for stuff moved as part of this branch.

* Fix stuff needed to merge with balloob's branch.

* Formatting issues.

* Missing __init__.py files.

* Fix-ups

* Fixup

* Regenerated requirements.

* Linting errors fixed.

* Fixed more broken tests.

* Missing init files.

* Fix broken tests.

* More broken tests

* There seems to be a thread race condition.
I suspect the logger stuff is running in another thread, which means waiting until the aio loop is done is missing the log messages.
Used sleep instead because that allows the logger thread to run. I think the api_streams sensor might not be thread safe.

* Disabled tests, will remove sensor in #22147

* Updated coverage and codeowners.
2019-03-18 23:07:39 -07:00

400 lines
14 KiB
Python

"""The tests for the webdav calendar component."""
# pylint: disable=protected-access
import datetime
import logging
import unittest
from unittest.mock import (patch, Mock, MagicMock)
import homeassistant.components.calendar as calendar_base
import homeassistant.components.caldav.calendar as caldav
from caldav.objects import Event
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON
from homeassistant.util import dt
from tests.common import get_test_home_assistant
TEST_PLATFORM = {calendar_base.DOMAIN: {CONF_PLATFORM: 'test'}}
_LOGGER = logging.getLogger(__name__)
DEVICE_DATA = {
"name": "Private Calendar",
"device_id": "Private Calendar",
}
EVENTS = [
"""BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//E-Corp.//CalDAV Client//EN
BEGIN:VEVENT
UID:1
DTSTAMP:20171125T000000Z
DTSTART:20171127T170000Z
DTEND:20171127T180000Z
SUMMARY:This is a normal event
LOCATION:Hamburg
DESCRIPTION:Surprisingly rainy
END:VEVENT
END:VCALENDAR
""",
"""BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Global Dynamics.//CalDAV Client//EN
BEGIN:VEVENT
UID:2
DTSTAMP:20171125T000000Z
DTSTART:20171127T100000Z
DTEND:20171127T110000Z
SUMMARY:This is an offset event !!-02:00
LOCATION:Hamburg
DESCRIPTION:Surprisingly shiny
END:VEVENT
END:VCALENDAR
""",
"""BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Global Corp.//CalDAV Client//EN
BEGIN:VEVENT
UID:3
DTSTAMP:20171125T000000Z
DTSTART:20171127
DTEND:20171128
SUMMARY:This is an all day event
LOCATION:Hamburg
DESCRIPTION:What a beautiful day
END:VEVENT
END:VCALENDAR
""",
"""BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Global Corp.//CalDAV Client//EN
BEGIN:VEVENT
UID:4
DTSTAMP:20171125T000000Z
DTSTART:20171127
SUMMARY:This is an event without dtend or duration
LOCATION:Hamburg
DESCRIPTION:What an endless day
END:VEVENT
END:VCALENDAR
""",
"""BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Global Corp.//CalDAV Client//EN
BEGIN:VEVENT
UID:5
DTSTAMP:20171125T000000Z
DTSTART:20171127
DURATION:PT1H
SUMMARY:This is an event with duration
LOCATION:Hamburg
DESCRIPTION:What a day
END:VEVENT
END:VCALENDAR
""",
"""BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Global Corp.//CalDAV Client//EN
BEGIN:VEVENT
UID:6
DTSTAMP:20171125T000000Z
DTSTART:20171127T100000Z
DURATION:PT1H
SUMMARY:This is an event with duration
LOCATION:Hamburg
DESCRIPTION:What a day
END:VEVENT
END:VCALENDAR
""",
"""BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Global Corp.//CalDAV Client//EN
BEGIN:VEVENT
UID:7
DTSTART;TZID=America/Los_Angeles:20171127T083000
DTSTAMP:20180301T020053Z
DTEND;TZID=America/Los_Angeles:20171127T093000
SUMMARY:Enjoy the sun
LOCATION:San Francisco
DESCRIPTION:Sunny day
END:VEVENT
END:VCALENDAR
"""
]
def _local_datetime(hours, minutes):
"""Build a datetime object for testing in the correct timezone."""
return dt.as_local(datetime.datetime(2017, 11, 27, hours, minutes, 0))
def _mocked_dav_client(*args, **kwargs):
"""Mock requests.get invocations."""
calendars = [
_mock_calendar("First"),
_mock_calendar("Second")
]
principal = Mock()
principal.calendars = MagicMock(return_value=calendars)
client = Mock()
client.principal = MagicMock(return_value=principal)
return client
def _mock_calendar(name):
events = []
for idx, event in enumerate(EVENTS):
events.append(Event(None, "%d.ics" % idx, event, None, str(idx)))
calendar = Mock()
calendar.date_search = MagicMock(return_value=events)
calendar.name = name
return calendar
class TestComponentsWebDavCalendar(unittest.TestCase):
"""Test the WebDav calendar."""
hass = None # HomeAssistant
# pylint: disable=invalid-name
def setUp(self):
"""Set up things to be run when tests are started."""
self.hass = get_test_home_assistant()
self.hass.http = Mock()
self.calendar = _mock_calendar("Private")
# pylint: disable=invalid-name
def tearDown(self):
"""Stop everything that was started."""
self.hass.stop()
@patch('caldav.DAVClient', side_effect=_mocked_dav_client)
def test_setup_component(self, req_mock):
"""Test setup component with calendars."""
def _add_device(devices):
assert len(devices) == 2
assert devices[0].name == "First"
assert devices[0].dev_id == "First"
assert not devices[0].data.include_all_day
assert devices[1].name == "Second"
assert devices[1].dev_id == "Second"
assert not devices[1].data.include_all_day
caldav.setup_platform(self.hass,
{
"url": "http://test.local",
"custom_calendars": []
},
_add_device)
@patch('caldav.DAVClient', side_effect=_mocked_dav_client)
def test_setup_component_with_no_calendar_matching(self, req_mock):
"""Test setup component with wrong calendar."""
def _add_device(devices):
assert not devices
caldav.setup_platform(self.hass,
{
"url": "http://test.local",
"calendars": ["none"],
"custom_calendars": []
},
_add_device)
@patch('caldav.DAVClient', side_effect=_mocked_dav_client)
def test_setup_component_with_a_calendar_match(self, req_mock):
"""Test setup component with right calendar."""
def _add_device(devices):
assert len(devices) == 1
assert devices[0].name == "Second"
caldav.setup_platform(self.hass,
{
"url": "http://test.local",
"calendars": ["Second"],
"custom_calendars": []
},
_add_device)
@patch('caldav.DAVClient', side_effect=_mocked_dav_client)
def test_setup_component_with_one_custom_calendar(self, req_mock):
"""Test setup component with custom calendars."""
def _add_device(devices):
assert len(devices) == 1
assert devices[0].name == "HomeOffice"
assert devices[0].dev_id == "Second HomeOffice"
assert devices[0].data.include_all_day
caldav.setup_platform(self.hass,
{
"url": "http://test.local",
"custom_calendars": [
{
"name": "HomeOffice",
"calendar": "Second",
"filter": "HomeOffice"
}]
},
_add_device)
@patch('homeassistant.util.dt.now', return_value=_local_datetime(17, 45))
def test_ongoing_event(self, mock_now):
"""Test that the ongoing event is returned."""
cal = caldav.WebDavCalendarEventDevice(self.hass,
DEVICE_DATA,
self.calendar)
assert cal.name == DEVICE_DATA["name"]
assert cal.state == STATE_ON
assert cal.device_state_attributes == {
"message": "This is a normal event",
"all_day": False,
"offset_reached": False,
"start_time": "2017-11-27 17:00:00",
"end_time": "2017-11-27 18:00:00",
"location": "Hamburg",
"description": "Surprisingly rainy",
}
@patch('homeassistant.util.dt.now', return_value=_local_datetime(17, 30))
def test_just_ended_event(self, mock_now):
"""Test that the next ongoing event is returned."""
cal = caldav.WebDavCalendarEventDevice(self.hass,
DEVICE_DATA,
self.calendar)
assert cal.name == DEVICE_DATA["name"]
assert cal.state == STATE_ON
assert cal.device_state_attributes == {
"message": "This is a normal event",
"all_day": False,
"offset_reached": False,
"start_time": "2017-11-27 17:00:00",
"end_time": "2017-11-27 18:00:00",
"location": "Hamburg",
"description": "Surprisingly rainy",
}
@patch('homeassistant.util.dt.now', return_value=_local_datetime(17, 00))
def test_ongoing_event_different_tz(self, mock_now):
"""Test that the ongoing event with another timezone is returned."""
cal = caldav.WebDavCalendarEventDevice(self.hass,
DEVICE_DATA,
self.calendar)
assert cal.name == DEVICE_DATA["name"]
assert cal.state == STATE_ON
assert cal.device_state_attributes == {
"message": "Enjoy the sun",
"all_day": False,
"offset_reached": False,
"start_time": "2017-11-27 16:30:00",
"description": "Sunny day",
"end_time": "2017-11-27 17:30:00",
"location": "San Francisco",
}
@patch('homeassistant.util.dt.now', return_value=_local_datetime(8, 30))
def test_ongoing_event_with_offset(self, mock_now):
"""Test that the offset is taken into account."""
cal = caldav.WebDavCalendarEventDevice(self.hass,
DEVICE_DATA,
self.calendar)
assert cal.state == STATE_OFF
assert cal.device_state_attributes == {
"message": "This is an offset event",
"all_day": False,
"offset_reached": True,
"start_time": "2017-11-27 10:00:00",
"end_time": "2017-11-27 11:00:00",
"location": "Hamburg",
"description": "Surprisingly shiny",
}
@patch('homeassistant.util.dt.now', return_value=_local_datetime(12, 00))
def test_matching_filter(self, mock_now):
"""Test that the matching event is returned."""
cal = caldav.WebDavCalendarEventDevice(self.hass,
DEVICE_DATA,
self.calendar,
False,
"This is a normal event")
assert cal.state == STATE_OFF
assert not cal.offset_reached()
assert cal.device_state_attributes == {
"message": "This is a normal event",
"all_day": False,
"offset_reached": False,
"start_time": "2017-11-27 17:00:00",
"end_time": "2017-11-27 18:00:00",
"location": "Hamburg",
"description": "Surprisingly rainy",
}
@patch('homeassistant.util.dt.now', return_value=_local_datetime(12, 00))
def test_matching_filter_real_regexp(self, mock_now):
"""Test that the event matching the regexp is returned."""
cal = caldav.WebDavCalendarEventDevice(self.hass,
DEVICE_DATA,
self.calendar,
False,
"^This.*event")
assert cal.state == STATE_OFF
assert not cal.offset_reached()
assert cal.device_state_attributes == {
"message": "This is a normal event",
"all_day": False,
"offset_reached": False,
"start_time": "2017-11-27 17:00:00",
"end_time": "2017-11-27 18:00:00",
"location": "Hamburg",
"description": "Surprisingly rainy",
}
@patch('homeassistant.util.dt.now', return_value=_local_datetime(20, 00))
def test_filter_matching_past_event(self, mock_now):
"""Test that the matching past event is not returned."""
cal = caldav.WebDavCalendarEventDevice(self.hass,
DEVICE_DATA,
self.calendar,
False,
"This is a normal event")
assert cal.data.event is None
@patch('homeassistant.util.dt.now', return_value=_local_datetime(12, 00))
def test_no_result_with_filtering(self, mock_now):
"""Test that nothing is returned since nothing matches."""
cal = caldav.WebDavCalendarEventDevice(self.hass,
DEVICE_DATA,
self.calendar,
False,
"This is a non-existing event")
assert cal.data.event is None
@patch('homeassistant.util.dt.now', return_value=_local_datetime(17, 30))
def test_all_day_event_returned(self, mock_now):
"""Test that the event lasting the whole day is returned."""
cal = caldav.WebDavCalendarEventDevice(self.hass,
DEVICE_DATA,
self.calendar,
True)
assert cal.name == DEVICE_DATA["name"]
assert cal.state == STATE_ON
assert cal.device_state_attributes == {
"message": "This is an all day event",
"all_day": True,
"offset_reached": False,
"start_time": "2017-11-27 00:00:00",
"end_time": "2017-11-28 00:00:00",
"location": "Hamburg",
"description": "What a beautiful day",
}