Simplify google calendar authentication to combine some of the cases together, and reduce unecessarily checks. Make the tests share common authentication setup and reduce use of mocks by introducing a fake for holding on to credentials. This makes future refactoring simpler, so we don't have to care as much about the interactions with the credentials storage.
150 lines
4.1 KiB
Python
150 lines
4.1 KiB
Python
"""Test configuration and mocks for the google integration."""
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
import datetime
|
|
from typing import Any, Generator, TypeVar
|
|
from unittest.mock import Mock, patch
|
|
|
|
from oauth2client.client import Credentials, OAuth2Credentials
|
|
import pytest
|
|
|
|
from homeassistant.components.google import GoogleCalendarService
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.util.dt import utcnow
|
|
|
|
ApiResult = Callable[[dict[str, Any]], None]
|
|
T = TypeVar("T")
|
|
YieldFixture = Generator[T, None, None]
|
|
|
|
|
|
CALENDAR_ID = "qwertyuiopasdfghjklzxcvbnm@import.calendar.google.com"
|
|
TEST_CALENDAR = {
|
|
"id": CALENDAR_ID,
|
|
"etag": '"3584134138943410"',
|
|
"timeZone": "UTC",
|
|
"accessRole": "reader",
|
|
"foregroundColor": "#000000",
|
|
"selected": True,
|
|
"kind": "calendar#calendarListEntry",
|
|
"backgroundColor": "#16a765",
|
|
"description": "Test Calendar",
|
|
"summary": "We are, we are, a... Test Calendar",
|
|
"colorId": "8",
|
|
"defaultReminders": [],
|
|
"track": True,
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def test_calendar():
|
|
"""Return a test calendar."""
|
|
return TEST_CALENDAR
|
|
|
|
|
|
class FakeStorage:
|
|
"""A fake storage object for persiting creds."""
|
|
|
|
def __init__(self) -> None:
|
|
"""Initialize FakeStorage."""
|
|
self._creds: Credentials | None = None
|
|
|
|
def get(self) -> Credentials | None:
|
|
"""Get credentials from storage."""
|
|
return self._creds
|
|
|
|
def put(self, creds: Credentials) -> None:
|
|
"""Put credentials in storage."""
|
|
self._creds = creds
|
|
|
|
|
|
@pytest.fixture
|
|
async def token_scopes() -> list[str]:
|
|
"""Fixture for scopes used during test."""
|
|
return ["https://www.googleapis.com/auth/calendar"]
|
|
|
|
|
|
@pytest.fixture
|
|
async def creds(token_scopes: list[str]) -> OAuth2Credentials:
|
|
"""Fixture that defines creds used in the test."""
|
|
token_expiry = utcnow() + datetime.timedelta(days=7)
|
|
return OAuth2Credentials(
|
|
access_token="ACCESS_TOKEN",
|
|
client_id="client-id",
|
|
client_secret="client-secret",
|
|
refresh_token="REFRESH_TOKEN",
|
|
token_expiry=token_expiry,
|
|
token_uri="http://example.com",
|
|
user_agent="n/a",
|
|
scopes=token_scopes,
|
|
)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
async def storage() -> YieldFixture[FakeStorage]:
|
|
"""Fixture to populate an existing token file for read on startup."""
|
|
storage = FakeStorage()
|
|
with patch("homeassistant.components.google.Storage", return_value=storage):
|
|
yield storage
|
|
|
|
|
|
@pytest.fixture
|
|
async def mock_token_read(
|
|
hass: HomeAssistant,
|
|
creds: OAuth2Credentials,
|
|
storage: FakeStorage,
|
|
) -> None:
|
|
"""Fixture to populate an existing token file for read on startup."""
|
|
storage.put(creds)
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_next_event():
|
|
"""Mock the google calendar data."""
|
|
patch_google_cal = patch(
|
|
"homeassistant.components.google.calendar.GoogleCalendarData"
|
|
)
|
|
with patch_google_cal as google_cal_data:
|
|
yield google_cal_data
|
|
|
|
|
|
@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
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_calendars_list(
|
|
google_service: GoogleCalendarService,
|
|
) -> ApiResult:
|
|
"""Fixture to construct a fake calendar list API response."""
|
|
|
|
def _put_result(response: dict[str, Any]) -> None:
|
|
google_service.return_value.get.return_value.calendarList.return_value.list.return_value.execute.return_value = (
|
|
response
|
|
)
|
|
return
|
|
|
|
return _put_result
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_insert_event(
|
|
google_service: GoogleCalendarService,
|
|
) -> Mock:
|
|
"""Fixture to create a mock to capture new events added to the API."""
|
|
insert_mock = Mock()
|
|
google_service.return_value.get.return_value.events.return_value.insert = (
|
|
insert_mock
|
|
)
|
|
return insert_mock
|