Increase test coverage for google calendar (#62648)

* Increase test coverage for google calendar

Update tests to exercise the API responses, getting test coverage
to 97% for calendar.py

----------- coverage: platform linux, python 3.9.6-final-0 -----------
Name                                          Stmts   Miss  Cover   Missing
---------------------------------------------------------------------------
homeassistant/components/google/__init__.py     193     84    56%   92, 163-228, 238, 244-247, 254-262, 274, 298-299, 305-347, 387-392, 416-430, 435-437
homeassistant/components/google/calendar.py     122      4    97%   41, 45, 51, 135
---------------------------------------------------------------------------
TOTAL                                           315     88    72%

* Revert conftest changes

* Update typing errors found on CI

* Update python3.8 typing imports

* Remove commented out code
This commit is contained in:
Allen Porter 2021-12-22 22:31:56 -08:00 committed by GitHub
parent 6ef7539a31
commit 23277181ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 170 additions and 9 deletions

View file

@ -399,7 +399,7 @@ omit =
homeassistant/components/glances/sensor.py homeassistant/components/glances/sensor.py
homeassistant/components/gntp/notify.py homeassistant/components/gntp/notify.py
homeassistant/components/goalfeed/* homeassistant/components/goalfeed/*
homeassistant/components/google/* homeassistant/components/google/__init__.py
homeassistant/components/google_cloud/tts.py homeassistant/components/google_cloud/tts.py
homeassistant/components/google_maps/device_tracker.py homeassistant/components/google_maps/device_tracker.py
homeassistant/components/google_pubsub/__init__.py homeassistant/components/google_pubsub/__init__.py

View file

@ -121,8 +121,8 @@ class GoogleCalendarData:
def _prepare_query(self): def _prepare_query(self):
try: try:
service = self.calendar_service.get() service = self.calendar_service.get()
except ServerNotFoundError: except ServerNotFoundError as err:
_LOGGER.error("Unable to connect to Google") _LOGGER.error("Unable to connect to Google: %s", err)
return None, None return None, None
params = dict(DEFAULT_GOOGLE_SEARCH_PARAMS) params = dict(DEFAULT_GOOGLE_SEARCH_PARAMS)
params["calendarId"] = self.calendar_id params["calendarId"] = self.calendar_id

View file

@ -1,5 +1,10 @@
"""The tests for the google calendar platform.""" """The tests for the google calendar platform."""
from __future__ import annotations
import copy import copy
from http import HTTPStatus
from typing import Any, Callable
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
import httplib2 import httplib2
@ -11,10 +16,12 @@ from homeassistant.components.google import (
CONF_CLIENT_SECRET, CONF_CLIENT_SECRET,
CONF_DEVICE_ID, CONF_DEVICE_ID,
CONF_ENTITIES, CONF_ENTITIES,
CONF_IGNORE_AVAILABILITY,
CONF_NAME, CONF_NAME,
CONF_TRACK, CONF_TRACK,
DEVICE_SCHEMA, DEVICE_SCHEMA,
SERVICE_SCAN_CALENDARS, SERVICE_SCAN_CALENDARS,
GoogleCalendarService,
do_setup, do_setup,
) )
from homeassistant.const import STATE_OFF, STATE_ON from homeassistant.const import STATE_OFF, STATE_ON
@ -23,6 +30,8 @@ from homeassistant.setup import async_setup_component
from homeassistant.util import slugify from homeassistant.util import slugify
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from .conftest import TEST_CALENDAR
from tests.common import async_mock_service from tests.common import async_mock_service
GOOGLE_CONFIG = {CONF_CLIENT_ID: "client_id", CONF_CLIENT_SECRET: "client_secret"} GOOGLE_CONFIG = {CONF_CLIENT_ID: "client_id", CONF_CLIENT_SECRET: "client_secret"}
@ -69,6 +78,7 @@ def get_calendar_info(calendar):
CONF_TRACK: calendar["track"], CONF_TRACK: calendar["track"],
CONF_NAME: calendar["summary"], CONF_NAME: calendar["summary"],
CONF_DEVICE_ID: slugify(calendar["summary"]), CONF_DEVICE_ID: slugify(calendar["summary"]),
CONF_IGNORE_AVAILABILITY: calendar.get("ignore_availability", True),
} }
], ],
} }
@ -95,12 +105,6 @@ def mock_google_setup(hass, test_calendar):
yield yield
@pytest.fixture(autouse=True)
def mock_http(hass):
"""Mock the http component."""
hass.http = Mock()
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def set_time_zone(): def set_time_zone():
"""Set the time zone for the tests.""" """Set the time zone for the tests."""
@ -314,3 +318,160 @@ async def test_update_error(hass, google_service):
state = hass.states.get(TEST_ENTITY) state = hass.states.get(TEST_ENTITY)
assert state.name == TEST_ENTITY_NAME assert state.name == TEST_ENTITY_NAME
assert state.state == "off" assert state.state == "off"
async def test_calendars_api(hass, hass_client, google_service):
"""Test the Rest API returns the calendar."""
assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG})
await hass.async_block_till_done()
client = await hass_client()
response = await client.get("/api/calendars")
assert response.status == HTTPStatus.OK
data = await response.json()
assert data == [
{
"entity_id": TEST_ENTITY,
"name": TEST_ENTITY_NAME,
}
]
async def test_http_event_api_failure(hass, hass_client, google_service):
"""Test the Rest API response during a calendar failure."""
google_service.return_value.get = Mock(
side_effect=httplib2.ServerNotFoundError("unit test")
)
assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG})
await hass.async_block_till_done()
start = dt_util.now().isoformat()
end = (dt_util.now() + dt_util.dt.timedelta(minutes=60)).isoformat()
client = await hass_client()
response = await client.get(f"/api/calendars/{TEST_ENTITY}?start={start}&end={end}")
assert response.status == HTTPStatus.OK
# A failure to talk to the server results in an empty list of events
events = await response.json()
assert events == []
@pytest.fixture
def mock_events_list(
google_service: GoogleCalendarService,
) -> Callable[[dict[str, Any]], None]:
"""Fixture to construct a fake event list API response."""
def _put_result(response: dict[str, Any]) -> None:
google_service.return_value.get.return_value.events.return_value.list.return_value.execute.return_value = (
response
)
return
return _put_result
async def test_http_api_event(hass, hass_client, google_service, mock_events_list):
"""Test querying the API and fetching events from the server."""
now = dt_util.now()
mock_events_list(
{
"items": [
{
"summary": "Event title",
"start": {"dateTime": now.isoformat()},
"end": {
"dateTime": (now + dt_util.dt.timedelta(minutes=5)).isoformat()
},
}
],
}
)
assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG})
await hass.async_block_till_done()
start = (now - dt_util.dt.timedelta(minutes=60)).isoformat()
end = (now + dt_util.dt.timedelta(minutes=60)).isoformat()
client = await hass_client()
response = await client.get(f"/api/calendars/{TEST_ENTITY}?start={start}&end={end}")
assert response.status == HTTPStatus.OK
events = await response.json()
assert len(events) == 1
assert "summary" in events[0]
assert events[0]["summary"] == "Event title"
def create_ignore_avail_calendar() -> dict[str, Any]:
"""Create a calendar with ignore_availability set."""
calendar = TEST_CALENDAR.copy()
calendar["ignore_availability"] = False
return calendar
@pytest.mark.parametrize("test_calendar", [create_ignore_avail_calendar()])
async def test_opaque_event(hass, hass_client, google_service, mock_events_list):
"""Test querying the API and fetching events from the server."""
now = dt_util.now()
mock_events_list(
{
"items": [
{
"summary": "Event title",
"transparency": "opaque",
"start": {"dateTime": now.isoformat()},
"end": {
"dateTime": (now + dt_util.dt.timedelta(minutes=5)).isoformat()
},
}
],
}
)
assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG})
await hass.async_block_till_done()
start = (now - dt_util.dt.timedelta(minutes=60)).isoformat()
end = (now + dt_util.dt.timedelta(minutes=60)).isoformat()
client = await hass_client()
response = await client.get(f"/api/calendars/{TEST_ENTITY}?start={start}&end={end}")
assert response.status == HTTPStatus.OK
events = await response.json()
assert len(events) == 1
assert "summary" in events[0]
assert events[0]["summary"] == "Event title"
@pytest.mark.parametrize("test_calendar", [create_ignore_avail_calendar()])
async def test_transparent_event(hass, hass_client, google_service, mock_events_list):
"""Test querying the API and fetching events from the server."""
now = dt_util.now()
mock_events_list(
{
"items": [
{
"summary": "Event title",
"transparency": "transparent",
"start": {"dateTime": now.isoformat()},
"end": {
"dateTime": (now + dt_util.dt.timedelta(minutes=5)).isoformat()
},
}
],
}
)
assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG})
await hass.async_block_till_done()
start = (now - dt_util.dt.timedelta(minutes=60)).isoformat()
end = (now + dt_util.dt.timedelta(minutes=60)).isoformat()
client = await hass_client()
response = await client.get(f"/api/calendars/{TEST_ENTITY}?start={start}&end={end}")
assert response.status == HTTPStatus.OK
events = await response.json()
assert events == []