mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 22:27:07 +00:00
Add Calendar API endpoint to get events (#14702)
* Add Calendar API endpoint to get events * Set default event color * Fix PR comments * Fix PR comments * Fix PR comments * Remote local.py file * Use iso 8601 * Fix lint * Fix PR comments * Fix PR comments * Add Support for todoist and demo calendar * Todoist events are allday events * Add calendar demo api endpoint test * Register only one api endpoint for calendar * Rename demo calendar
This commit is contained in:
parent
1128104281
commit
3cd4cb741c
@ -9,6 +9,8 @@ import logging
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from aiohttp import web
|
||||||
|
|
||||||
from homeassistant.components.google import (
|
from homeassistant.components.google import (
|
||||||
CONF_OFFSET, CONF_DEVICE_ID, CONF_NAME)
|
CONF_OFFSET, CONF_DEVICE_ID, CONF_NAME)
|
||||||
from homeassistant.const import STATE_OFF, STATE_ON
|
from homeassistant.const import STATE_OFF, STATE_ON
|
||||||
@ -18,11 +20,15 @@ from homeassistant.helpers.entity import Entity, generate_entity_id
|
|||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
from homeassistant.helpers.template import DATE_STR_FORMAT
|
from homeassistant.helpers.template import DATE_STR_FORMAT
|
||||||
from homeassistant.util import dt
|
from homeassistant.util import dt
|
||||||
|
from homeassistant.components import http
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOMAIN = 'calendar'
|
DOMAIN = 'calendar'
|
||||||
|
|
||||||
|
DEPENDENCIES = ['http']
|
||||||
|
|
||||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
|
|
||||||
SCAN_INTERVAL = timedelta(seconds=60)
|
SCAN_INTERVAL = timedelta(seconds=60)
|
||||||
@ -34,6 +40,8 @@ def async_setup(hass, config):
|
|||||||
component = EntityComponent(
|
component = EntityComponent(
|
||||||
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, DOMAIN)
|
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, DOMAIN)
|
||||||
|
|
||||||
|
hass.http.register_view(CalendarEventView(component))
|
||||||
|
|
||||||
yield from component.async_setup(config)
|
yield from component.async_setup(config)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -42,6 +50,14 @@ DEFAULT_CONF_TRACK_NEW = True
|
|||||||
DEFAULT_CONF_OFFSET = '!!'
|
DEFAULT_CONF_OFFSET = '!!'
|
||||||
|
|
||||||
|
|
||||||
|
def get_date(date):
|
||||||
|
"""Get the dateTime from date or dateTime as a local."""
|
||||||
|
if 'date' in date:
|
||||||
|
return dt.start_of_local_day(dt.dt.datetime.combine(
|
||||||
|
dt.parse_date(date['date']), dt.dt.time.min))
|
||||||
|
return dt.as_local(dt.parse_datetime(date['dateTime']))
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-many-instance-attributes
|
# pylint: disable=too-many-instance-attributes
|
||||||
class CalendarEventDevice(Entity):
|
class CalendarEventDevice(Entity):
|
||||||
"""A calendar event device."""
|
"""A calendar event device."""
|
||||||
@ -144,15 +160,8 @@ class CalendarEventDevice(Entity):
|
|||||||
self.cleanup()
|
self.cleanup()
|
||||||
return
|
return
|
||||||
|
|
||||||
def _get_date(date):
|
start = get_date(self.data.event['start'])
|
||||||
"""Get the dateTime from date or dateTime as a local."""
|
end = get_date(self.data.event['end'])
|
||||||
if 'date' in date:
|
|
||||||
return dt.start_of_local_day(dt.dt.datetime.combine(
|
|
||||||
dt.parse_date(date['date']), dt.dt.time.min))
|
|
||||||
return dt.as_local(dt.parse_datetime(date['dateTime']))
|
|
||||||
|
|
||||||
start = _get_date(self.data.event['start'])
|
|
||||||
end = _get_date(self.data.event['end'])
|
|
||||||
|
|
||||||
summary = self.data.event.get('summary', '')
|
summary = self.data.event.get('summary', '')
|
||||||
|
|
||||||
@ -176,10 +185,37 @@ class CalendarEventDevice(Entity):
|
|||||||
|
|
||||||
# cleanup the string so we don't have a bunch of double+ spaces
|
# cleanup the string so we don't have a bunch of double+ spaces
|
||||||
self._cal_data['message'] = re.sub(' +', '', summary).strip()
|
self._cal_data['message'] = re.sub(' +', '', summary).strip()
|
||||||
|
|
||||||
self._cal_data['offset_time'] = offset_time
|
self._cal_data['offset_time'] = offset_time
|
||||||
self._cal_data['location'] = self.data.event.get('location', '')
|
self._cal_data['location'] = self.data.event.get('location', '')
|
||||||
self._cal_data['description'] = self.data.event.get('description', '')
|
self._cal_data['description'] = self.data.event.get('description', '')
|
||||||
self._cal_data['start'] = start
|
self._cal_data['start'] = start
|
||||||
self._cal_data['end'] = end
|
self._cal_data['end'] = end
|
||||||
self._cal_data['all_day'] = 'date' in self.data.event['start']
|
self._cal_data['all_day'] = 'date' in self.data.event['start']
|
||||||
|
|
||||||
|
|
||||||
|
class CalendarEventView(http.HomeAssistantView):
|
||||||
|
"""View to retrieve calendar content."""
|
||||||
|
|
||||||
|
url = '/api/calendar/{entity_id}'
|
||||||
|
name = 'api:calendar'
|
||||||
|
|
||||||
|
def __init__(self, component):
|
||||||
|
"""Initialize calendar view."""
|
||||||
|
self.component = component
|
||||||
|
|
||||||
|
async def get(self, request, entity_id):
|
||||||
|
"""Return calendar events."""
|
||||||
|
entity = self.component.get_entity('calendar.' + entity_id)
|
||||||
|
start = request.query.get('start')
|
||||||
|
end = request.query.get('end')
|
||||||
|
if None in (start, end, entity):
|
||||||
|
return web.Response(status=400)
|
||||||
|
try:
|
||||||
|
start_date = dt.parse_datetime(start)
|
||||||
|
end_date = dt.parse_datetime(end)
|
||||||
|
except (ValueError, AttributeError):
|
||||||
|
return web.Response(status=400)
|
||||||
|
event_list = await entity.async_get_events(request.app['hass'],
|
||||||
|
start_date,
|
||||||
|
end_date)
|
||||||
|
return self.json(event_list)
|
||||||
|
@ -11,7 +11,7 @@ import re
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.calendar import (
|
from homeassistant.components.calendar import (
|
||||||
PLATFORM_SCHEMA, CalendarEventDevice)
|
PLATFORM_SCHEMA, CalendarEventDevice, get_date)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_NAME, CONF_PASSWORD, CONF_URL, CONF_USERNAME)
|
CONF_NAME, CONF_PASSWORD, CONF_URL, CONF_USERNAME)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
@ -92,7 +92,7 @@ def setup_platform(hass, config, add_devices, disc_info=None):
|
|||||||
if not config.get(CONF_CUSTOM_CALENDARS):
|
if not config.get(CONF_CUSTOM_CALENDARS):
|
||||||
device_data = {
|
device_data = {
|
||||||
CONF_NAME: calendar.name,
|
CONF_NAME: calendar.name,
|
||||||
CONF_DEVICE_ID: calendar.name
|
CONF_DEVICE_ID: calendar.name,
|
||||||
}
|
}
|
||||||
calendar_devices.append(
|
calendar_devices.append(
|
||||||
WebDavCalendarEventDevice(hass, device_data, calendar)
|
WebDavCalendarEventDevice(hass, device_data, calendar)
|
||||||
@ -120,6 +120,10 @@ class WebDavCalendarEventDevice(CalendarEventDevice):
|
|||||||
attributes = super().device_state_attributes
|
attributes = super().device_state_attributes
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
|
async def async_get_events(self, hass, start_date, end_date):
|
||||||
|
"""Get all events in a specific time frame."""
|
||||||
|
return await self.data.async_get_events(hass, start_date, end_date)
|
||||||
|
|
||||||
|
|
||||||
class WebDavCalendarData(object):
|
class WebDavCalendarData(object):
|
||||||
"""Class to utilize the calendar dav client object to get next event."""
|
"""Class to utilize the calendar dav client object to get next event."""
|
||||||
@ -131,6 +135,33 @@ class WebDavCalendarData(object):
|
|||||||
self.search = search
|
self.search = search
|
||||||
self.event = None
|
self.event = None
|
||||||
|
|
||||||
|
async def async_get_events(self, hass, start_date, end_date):
|
||||||
|
"""Get all events in a specific time frame."""
|
||||||
|
# Get event list from the current calendar
|
||||||
|
vevent_list = await hass.async_add_job(self.calendar.date_search,
|
||||||
|
start_date, end_date)
|
||||||
|
event_list = []
|
||||||
|
for event in vevent_list:
|
||||||
|
vevent = event.instance.vevent
|
||||||
|
uid = None
|
||||||
|
if hasattr(vevent, 'uid'):
|
||||||
|
uid = vevent.uid.value
|
||||||
|
data = {
|
||||||
|
"uid": uid,
|
||||||
|
"title": vevent.summary.value,
|
||||||
|
"start": self.get_hass_date(vevent.dtstart.value),
|
||||||
|
"end": self.get_hass_date(self.get_end_date(vevent)),
|
||||||
|
"location": self.get_attr_value(vevent, "location"),
|
||||||
|
"description": self.get_attr_value(vevent, "description"),
|
||||||
|
}
|
||||||
|
|
||||||
|
data['start'] = get_date(data['start']).isoformat()
|
||||||
|
data['end'] = get_date(data['end']).isoformat()
|
||||||
|
|
||||||
|
event_list.append(data)
|
||||||
|
|
||||||
|
return event_list
|
||||||
|
|
||||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Get the latest data."""
|
"""Get the latest data."""
|
||||||
|
@ -4,8 +4,10 @@ Demo platform that has two fake binary sensors.
|
|||||||
For more details about this platform, please refer to the documentation
|
For more details about this platform, please refer to the documentation
|
||||||
https://home-assistant.io/components/demo/
|
https://home-assistant.io/components/demo/
|
||||||
"""
|
"""
|
||||||
|
import copy
|
||||||
|
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
from homeassistant.components.calendar import CalendarEventDevice
|
from homeassistant.components.calendar import CalendarEventDevice, get_date
|
||||||
from homeassistant.components.google import CONF_DEVICE_ID, CONF_NAME
|
from homeassistant.components.google import CONF_DEVICE_ID, CONF_NAME
|
||||||
|
|
||||||
|
|
||||||
@ -16,12 +18,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
add_devices([
|
add_devices([
|
||||||
DemoGoogleCalendar(hass, calendar_data_future, {
|
DemoGoogleCalendar(hass, calendar_data_future, {
|
||||||
CONF_NAME: 'Future Event',
|
CONF_NAME: 'Future Event',
|
||||||
CONF_DEVICE_ID: 'future_event',
|
CONF_DEVICE_ID: 'calendar_1',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
DemoGoogleCalendar(hass, calendar_data_current, {
|
DemoGoogleCalendar(hass, calendar_data_current, {
|
||||||
CONF_NAME: 'Current Event',
|
CONF_NAME: 'Current Event',
|
||||||
CONF_DEVICE_ID: 'current_event',
|
CONF_DEVICE_ID: 'calendar_2',
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -29,11 +31,21 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
class DemoGoogleCalendarData(object):
|
class DemoGoogleCalendarData(object):
|
||||||
"""Representation of a Demo Calendar element."""
|
"""Representation of a Demo Calendar element."""
|
||||||
|
|
||||||
|
event = {}
|
||||||
|
|
||||||
# pylint: disable=no-self-use
|
# pylint: disable=no-self-use
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Return true so entity knows we have new data."""
|
"""Return true so entity knows we have new data."""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
async def async_get_events(self, hass, start_date, end_date):
|
||||||
|
"""Get all events in a specific time frame."""
|
||||||
|
event = copy.copy(self.event)
|
||||||
|
event['title'] = event['summary']
|
||||||
|
event['start'] = get_date(event['start']).isoformat()
|
||||||
|
event['end'] = get_date(event['end']).isoformat()
|
||||||
|
return [event]
|
||||||
|
|
||||||
|
|
||||||
class DemoGoogleCalendarDataFuture(DemoGoogleCalendarData):
|
class DemoGoogleCalendarDataFuture(DemoGoogleCalendarData):
|
||||||
"""Representation of a Demo Calendar for a future event."""
|
"""Representation of a Demo Calendar for a future event."""
|
||||||
@ -80,3 +92,7 @@ class DemoGoogleCalendar(CalendarEventDevice):
|
|||||||
"""Initialize Google Calendar but without the API calls."""
|
"""Initialize Google Calendar but without the API calls."""
|
||||||
self.data = calendar_data
|
self.data = calendar_data
|
||||||
super().__init__(hass, data)
|
super().__init__(hass, data)
|
||||||
|
|
||||||
|
async def async_get_events(self, hass, start_date, end_date):
|
||||||
|
"""Get all events in a specific time frame."""
|
||||||
|
return await self.data.async_get_events(hass, start_date, end_date)
|
||||||
|
@ -51,6 +51,10 @@ class GoogleCalendarEventDevice(CalendarEventDevice):
|
|||||||
|
|
||||||
super().__init__(hass, data)
|
super().__init__(hass, data)
|
||||||
|
|
||||||
|
async def async_get_events(self, hass, start_date, end_date):
|
||||||
|
"""Get all events in a specific time frame."""
|
||||||
|
return await self.data.async_get_events(hass, start_date, end_date)
|
||||||
|
|
||||||
|
|
||||||
class GoogleCalendarData(object):
|
class GoogleCalendarData(object):
|
||||||
"""Class to utilize calendar service object to get next event."""
|
"""Class to utilize calendar service object to get next event."""
|
||||||
@ -64,9 +68,7 @@ class GoogleCalendarData(object):
|
|||||||
self.ignore_availability = ignore_availability
|
self.ignore_availability = ignore_availability
|
||||||
self.event = None
|
self.event = None
|
||||||
|
|
||||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
def _prepare_query(self):
|
||||||
def update(self):
|
|
||||||
"""Get the latest data."""
|
|
||||||
from httplib2 import ServerNotFoundError
|
from httplib2 import ServerNotFoundError
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -74,13 +76,41 @@ class GoogleCalendarData(object):
|
|||||||
except ServerNotFoundError:
|
except ServerNotFoundError:
|
||||||
_LOGGER.warning("Unable to connect to Google, using cached data")
|
_LOGGER.warning("Unable to connect to Google, using cached data")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
params = dict(DEFAULT_GOOGLE_SEARCH_PARAMS)
|
params = dict(DEFAULT_GOOGLE_SEARCH_PARAMS)
|
||||||
params['timeMin'] = dt.now().isoformat('T')
|
|
||||||
params['calendarId'] = self.calendar_id
|
params['calendarId'] = self.calendar_id
|
||||||
if self.search:
|
if self.search:
|
||||||
params['q'] = self.search
|
params['q'] = self.search
|
||||||
|
|
||||||
|
return service, params
|
||||||
|
|
||||||
|
async def async_get_events(self, hass, start_date, end_date):
|
||||||
|
"""Get all events in a specific time frame."""
|
||||||
|
service, params = await hass.async_add_job(self._prepare_query)
|
||||||
|
params['timeMin'] = start_date.isoformat('T')
|
||||||
|
params['timeMax'] = end_date.isoformat('T')
|
||||||
|
|
||||||
|
# pylint: disable=no-member
|
||||||
|
events = await hass.async_add_job(service.events)
|
||||||
|
# pylint: enable=no-member
|
||||||
|
result = await hass.async_add_job(events.list(**params).execute)
|
||||||
|
|
||||||
|
items = result.get('items', [])
|
||||||
|
event_list = []
|
||||||
|
for item in items:
|
||||||
|
if (not self.ignore_availability
|
||||||
|
and 'transparency' in item.keys()):
|
||||||
|
if item['transparency'] == 'opaque':
|
||||||
|
event_list.append(item)
|
||||||
|
else:
|
||||||
|
event_list.append(item)
|
||||||
|
return event_list
|
||||||
|
|
||||||
|
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||||
|
def update(self):
|
||||||
|
"""Get the latest data."""
|
||||||
|
service, params = self._prepare_query()
|
||||||
|
params['timeMin'] = dt.now().isoformat('T')
|
||||||
|
|
||||||
events = service.events() # pylint: disable=no-member
|
events = service.events() # pylint: disable=no-member
|
||||||
result = events.list(**params).execute()
|
result = events.list(**params).execute()
|
||||||
|
|
||||||
|
@ -257,6 +257,10 @@ class TodoistProjectDevice(CalendarEventDevice):
|
|||||||
super().cleanup()
|
super().cleanup()
|
||||||
self._cal_data[ALL_TASKS] = []
|
self._cal_data[ALL_TASKS] = []
|
||||||
|
|
||||||
|
async def async_get_events(self, hass, start_date, end_date):
|
||||||
|
"""Get all events in a specific time frame."""
|
||||||
|
return await self.data.async_get_events(hass, start_date, end_date)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the device state attributes."""
|
"""Return the device state attributes."""
|
||||||
@ -485,6 +489,31 @@ class TodoistProjectData(object):
|
|||||||
continue
|
continue
|
||||||
return event
|
return event
|
||||||
|
|
||||||
|
async def async_get_events(self, hass, start_date, end_date):
|
||||||
|
"""Get all tasks in a specific time frame."""
|
||||||
|
if self._id is None:
|
||||||
|
project_task_data = [
|
||||||
|
task for task in self._api.state[TASKS]
|
||||||
|
if not self._project_id_whitelist or
|
||||||
|
task[PROJECT_ID] in self._project_id_whitelist]
|
||||||
|
else:
|
||||||
|
project_task_data = self._api.projects.get_data(self._id)[TASKS]
|
||||||
|
|
||||||
|
events = []
|
||||||
|
time_format = '%a %d %b %Y %H:%M:%S %z'
|
||||||
|
for task in project_task_data:
|
||||||
|
due_date = datetime.strptime(task['due_date_utc'], time_format)
|
||||||
|
if due_date > start_date and due_date < end_date:
|
||||||
|
event = {
|
||||||
|
'uid': task['id'],
|
||||||
|
'title': task['content'],
|
||||||
|
'start': due_date.isoformat(),
|
||||||
|
'end': due_date.isoformat(),
|
||||||
|
'allDay': True,
|
||||||
|
}
|
||||||
|
events.append(event)
|
||||||
|
return events
|
||||||
|
|
||||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Get the latest data."""
|
"""Get the latest data."""
|
||||||
|
@ -19,7 +19,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
DEVICE_DATA = {
|
DEVICE_DATA = {
|
||||||
"name": "Private Calendar",
|
"name": "Private Calendar",
|
||||||
"device_id": "Private Calendar"
|
"device_id": "Private Calendar",
|
||||||
}
|
}
|
||||||
|
|
||||||
EVENTS = [
|
EVENTS = [
|
||||||
@ -163,6 +163,7 @@ class TestComponentsWebDavCalendar(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up things to be run when tests are started."""
|
"""Set up things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
|
self.hass.http = Mock()
|
||||||
self.calendar = _mock_calendar("Private")
|
self.calendar = _mock_calendar("Private")
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@ -255,7 +256,7 @@ class TestComponentsWebDavCalendar(unittest.TestCase):
|
|||||||
"start_time": "2017-11-27 17:00:00",
|
"start_time": "2017-11-27 17:00:00",
|
||||||
"end_time": "2017-11-27 18:00:00",
|
"end_time": "2017-11-27 18:00:00",
|
||||||
"location": "Hamburg",
|
"location": "Hamburg",
|
||||||
"description": "Surprisingly rainy"
|
"description": "Surprisingly rainy",
|
||||||
})
|
})
|
||||||
|
|
||||||
@patch('homeassistant.util.dt.now', return_value=_local_datetime(17, 30))
|
@patch('homeassistant.util.dt.now', return_value=_local_datetime(17, 30))
|
||||||
@ -274,7 +275,7 @@ class TestComponentsWebDavCalendar(unittest.TestCase):
|
|||||||
"start_time": "2017-11-27 17:00:00",
|
"start_time": "2017-11-27 17:00:00",
|
||||||
"end_time": "2017-11-27 18:00:00",
|
"end_time": "2017-11-27 18:00:00",
|
||||||
"location": "Hamburg",
|
"location": "Hamburg",
|
||||||
"description": "Surprisingly rainy"
|
"description": "Surprisingly rainy",
|
||||||
})
|
})
|
||||||
|
|
||||||
@patch('homeassistant.util.dt.now', return_value=_local_datetime(17, 00))
|
@patch('homeassistant.util.dt.now', return_value=_local_datetime(17, 00))
|
||||||
@ -293,7 +294,7 @@ class TestComponentsWebDavCalendar(unittest.TestCase):
|
|||||||
"start_time": "2017-11-27 16:30:00",
|
"start_time": "2017-11-27 16:30:00",
|
||||||
"description": "Sunny day",
|
"description": "Sunny day",
|
||||||
"end_time": "2017-11-27 17:30:00",
|
"end_time": "2017-11-27 17:30:00",
|
||||||
"location": "San Francisco"
|
"location": "San Francisco",
|
||||||
})
|
})
|
||||||
|
|
||||||
@patch('homeassistant.util.dt.now', return_value=_local_datetime(8, 30))
|
@patch('homeassistant.util.dt.now', return_value=_local_datetime(8, 30))
|
||||||
@ -311,7 +312,7 @@ class TestComponentsWebDavCalendar(unittest.TestCase):
|
|||||||
"start_time": "2017-11-27 10:00:00",
|
"start_time": "2017-11-27 10:00:00",
|
||||||
"end_time": "2017-11-27 11:00:00",
|
"end_time": "2017-11-27 11:00:00",
|
||||||
"location": "Hamburg",
|
"location": "Hamburg",
|
||||||
"description": "Surprisingly shiny"
|
"description": "Surprisingly shiny",
|
||||||
})
|
})
|
||||||
|
|
||||||
@patch('homeassistant.util.dt.now', return_value=_local_datetime(12, 00))
|
@patch('homeassistant.util.dt.now', return_value=_local_datetime(12, 00))
|
||||||
@ -332,7 +333,7 @@ class TestComponentsWebDavCalendar(unittest.TestCase):
|
|||||||
"start_time": "2017-11-27 17:00:00",
|
"start_time": "2017-11-27 17:00:00",
|
||||||
"end_time": "2017-11-27 18:00:00",
|
"end_time": "2017-11-27 18:00:00",
|
||||||
"location": "Hamburg",
|
"location": "Hamburg",
|
||||||
"description": "Surprisingly rainy"
|
"description": "Surprisingly rainy",
|
||||||
})
|
})
|
||||||
|
|
||||||
@patch('homeassistant.util.dt.now', return_value=_local_datetime(12, 00))
|
@patch('homeassistant.util.dt.now', return_value=_local_datetime(12, 00))
|
||||||
@ -353,7 +354,7 @@ class TestComponentsWebDavCalendar(unittest.TestCase):
|
|||||||
"start_time": "2017-11-27 17:00:00",
|
"start_time": "2017-11-27 17:00:00",
|
||||||
"end_time": "2017-11-27 18:00:00",
|
"end_time": "2017-11-27 18:00:00",
|
||||||
"location": "Hamburg",
|
"location": "Hamburg",
|
||||||
"description": "Surprisingly rainy"
|
"description": "Surprisingly rainy",
|
||||||
})
|
})
|
||||||
|
|
||||||
@patch('homeassistant.util.dt.now', return_value=_local_datetime(20, 00))
|
@patch('homeassistant.util.dt.now', return_value=_local_datetime(20, 00))
|
||||||
@ -395,5 +396,5 @@ class TestComponentsWebDavCalendar(unittest.TestCase):
|
|||||||
"start_time": "2017-11-27 00:00:00",
|
"start_time": "2017-11-27 00:00:00",
|
||||||
"end_time": "2017-11-28 00:00:00",
|
"end_time": "2017-11-28 00:00:00",
|
||||||
"location": "Hamburg",
|
"location": "Hamburg",
|
||||||
"description": "What a beautiful day"
|
"description": "What a beautiful day",
|
||||||
})
|
})
|
||||||
|
24
tests/components/calendar/test_demo.py
Normal file
24
tests/components/calendar/test_demo.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
"""The tests for the demo calendar component."""
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from homeassistant.bootstrap import async_setup_component
|
||||||
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
|
|
||||||
|
async def test_api_calendar_demo_view(hass, aiohttp_client):
|
||||||
|
"""Test the calendar demo view."""
|
||||||
|
await async_setup_component(hass, 'calendar',
|
||||||
|
{'calendar': {'platform': 'demo'}})
|
||||||
|
client = await aiohttp_client(hass.http.app)
|
||||||
|
response = await client.get(
|
||||||
|
'/api/calendar/calendar_2')
|
||||||
|
assert response.status == 400
|
||||||
|
start = dt_util.now()
|
||||||
|
end = start + timedelta(days=1)
|
||||||
|
response = await client.get(
|
||||||
|
'/api/calendar/calendar_1?start={}&end={}'.format(start.isoformat(),
|
||||||
|
end.isoformat()))
|
||||||
|
assert response.status == 200
|
||||||
|
events = await response.json()
|
||||||
|
assert events[0]['summary'] == 'Future Event'
|
||||||
|
assert events[0]['title'] == 'Future Event'
|
@ -27,6 +27,7 @@ class TestComponentsGoogleCalendar(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
|
self.hass.http = Mock()
|
||||||
|
|
||||||
# Set our timezone to CST/Regina so we can check calculations
|
# Set our timezone to CST/Regina so we can check calculations
|
||||||
# This keeps UTC-6 all year round
|
# This keeps UTC-6 all year round
|
||||||
@ -99,7 +100,7 @@ class TestComponentsGoogleCalendar(unittest.TestCase):
|
|||||||
'start_time': '{} 00:00:00'.format(event['start']['date']),
|
'start_time': '{} 00:00:00'.format(event['start']['date']),
|
||||||
'end_time': '{} 00:00:00'.format(event['end']['date']),
|
'end_time': '{} 00:00:00'.format(event['end']['date']),
|
||||||
'location': event['location'],
|
'location': event['location'],
|
||||||
'description': event['description']
|
'description': event['description'],
|
||||||
})
|
})
|
||||||
|
|
||||||
@patch('homeassistant.components.calendar.google.GoogleCalendarData')
|
@patch('homeassistant.components.calendar.google.GoogleCalendarData')
|
||||||
@ -160,7 +161,7 @@ class TestComponentsGoogleCalendar(unittest.TestCase):
|
|||||||
(one_hour_from_now + dt_util.dt.timedelta(minutes=60))
|
(one_hour_from_now + dt_util.dt.timedelta(minutes=60))
|
||||||
.strftime(DATE_STR_FORMAT),
|
.strftime(DATE_STR_FORMAT),
|
||||||
'location': '',
|
'location': '',
|
||||||
'description': ''
|
'description': '',
|
||||||
})
|
})
|
||||||
|
|
||||||
@patch('homeassistant.components.calendar.google.GoogleCalendarData')
|
@patch('homeassistant.components.calendar.google.GoogleCalendarData')
|
||||||
@ -222,7 +223,7 @@ class TestComponentsGoogleCalendar(unittest.TestCase):
|
|||||||
(middle_of_event + dt_util.dt.timedelta(minutes=60))
|
(middle_of_event + dt_util.dt.timedelta(minutes=60))
|
||||||
.strftime(DATE_STR_FORMAT),
|
.strftime(DATE_STR_FORMAT),
|
||||||
'location': '',
|
'location': '',
|
||||||
'description': ''
|
'description': '',
|
||||||
})
|
})
|
||||||
|
|
||||||
@patch('homeassistant.components.calendar.google.GoogleCalendarData')
|
@patch('homeassistant.components.calendar.google.GoogleCalendarData')
|
||||||
@ -285,7 +286,7 @@ class TestComponentsGoogleCalendar(unittest.TestCase):
|
|||||||
(middle_of_event + dt_util.dt.timedelta(minutes=60))
|
(middle_of_event + dt_util.dt.timedelta(minutes=60))
|
||||||
.strftime(DATE_STR_FORMAT),
|
.strftime(DATE_STR_FORMAT),
|
||||||
'location': '',
|
'location': '',
|
||||||
'description': ''
|
'description': '',
|
||||||
})
|
})
|
||||||
|
|
||||||
@pytest.mark.skip
|
@pytest.mark.skip
|
||||||
@ -352,7 +353,7 @@ class TestComponentsGoogleCalendar(unittest.TestCase):
|
|||||||
'start_time': '{} 06:00:00'.format(event['start']['date']),
|
'start_time': '{} 06:00:00'.format(event['start']['date']),
|
||||||
'end_time': '{} 06:00:00'.format(event['end']['date']),
|
'end_time': '{} 06:00:00'.format(event['end']['date']),
|
||||||
'location': event['location'],
|
'location': event['location'],
|
||||||
'description': event['description']
|
'description': event['description'],
|
||||||
})
|
})
|
||||||
|
|
||||||
@patch('homeassistant.components.calendar.google.GoogleCalendarData')
|
@patch('homeassistant.components.calendar.google.GoogleCalendarData')
|
||||||
@ -419,7 +420,7 @@ class TestComponentsGoogleCalendar(unittest.TestCase):
|
|||||||
'start_time': '{} 00:00:00'.format(event['start']['date']),
|
'start_time': '{} 00:00:00'.format(event['start']['date']),
|
||||||
'end_time': '{} 00:00:00'.format(event['end']['date']),
|
'end_time': '{} 00:00:00'.format(event['end']['date']),
|
||||||
'location': event['location'],
|
'location': event['location'],
|
||||||
'description': event['description']
|
'description': event['description'],
|
||||||
})
|
})
|
||||||
|
|
||||||
@MockDependency("httplib2")
|
@MockDependency("httplib2")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user