Simplify google calendar API interactions (#67319)

* Simplify google calendar APIs and tests

* Simplify authentication logic at startup

* Improve readability of diffs

* Reduce diffs

* Simplify api datetime logic

* Remove duplicate test fixtures added in prior commit

* Remove duplicate event filter calls

* Fix event list argument names

* More improvements found from additional testing

* Remove unnecessary variables in create event call
This commit is contained in:
Allen Porter 2022-02-26 16:19:45 -08:00 committed by GitHub
parent 479aa13211
commit deda9e38e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 152 additions and 153 deletions

View File

@ -7,8 +7,6 @@ from enum import Enum
import logging import logging
from typing import Any from typing import Any
from googleapiclient import discovery as google_discovery
import httplib2
from oauth2client.client import ( from oauth2client.client import (
FlowExchangeError, FlowExchangeError,
OAuth2DeviceCodeError, OAuth2DeviceCodeError,
@ -37,6 +35,8 @@ from homeassistant.helpers.event import track_utc_time_change
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.util import convert from homeassistant.util import convert
from .api import GoogleCalendarService
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN = "google" DOMAIN = "google"
@ -77,6 +77,7 @@ SERVICE_FOUND_CALENDARS = "found_calendar"
SERVICE_ADD_EVENT = "add_event" SERVICE_ADD_EVENT = "add_event"
DATA_CALENDARS = "calendars" DATA_CALENDARS = "calendars"
DATA_SERVICE = "service"
YAML_DEVICES = f"{DOMAIN}_calendars.yaml" YAML_DEVICES = f"{DOMAIN}_calendars.yaml"
@ -251,13 +252,16 @@ def do_authentication(
def setup(hass: HomeAssistant, config: ConfigType) -> bool: def setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Google platform.""" """Set up the Google platform."""
hass.data[DOMAIN] = {DATA_CALENDARS: {}}
if not (conf := config.get(DOMAIN, {})): if not (conf := config.get(DOMAIN, {})):
# component is set up by tts platform # component is set up by tts platform
return True return True
storage = Storage(hass.config.path(TOKEN_FILE)) storage = Storage(hass.config.path(TOKEN_FILE))
hass.data[DOMAIN] = {
DATA_CALENDARS: {},
DATA_SERVICE: GoogleCalendarService(hass, storage),
}
creds = storage.get() creds = storage.get()
if ( if (
not creds not creds
@ -271,34 +275,6 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
return True return True
def check_correct_scopes(
hass: HomeAssistant, token_file: str, config: ConfigType
) -> bool:
"""Check for the correct scopes in file."""
creds = Storage(token_file).get()
if not creds or not creds.scopes:
return False
target_scope = config[CONF_CALENDAR_ACCESS].scope
return target_scope in creds.scopes
class GoogleCalendarService:
"""Calendar service interface to Google."""
def __init__(self, token_file: str) -> None:
"""Init the Google Calendar service."""
self.token_file = token_file
def get(self) -> google_discovery.Resource:
"""Get the calendar service from the storage file token."""
credentials = Storage(self.token_file).get()
http = credentials.authorize(httplib2.Http())
service = google_discovery.build(
"calendar", "v3", http=http, cache_discovery=False
)
return service
def setup_services( def setup_services(
hass: HomeAssistant, hass: HomeAssistant,
hass_config: ConfigType, hass_config: ConfigType,
@ -328,9 +304,7 @@ def setup_services(
def _scan_for_calendars(call: ServiceCall) -> None: def _scan_for_calendars(call: ServiceCall) -> None:
"""Scan for new calendars.""" """Scan for new calendars."""
service = calendar_service.get() calendars = calendar_service.list_calendars()
cal_list = service.calendarList()
calendars = cal_list.list().execute()["items"]
for calendar in calendars: for calendar in calendars:
calendar["track"] = track_new_found_calendars calendar["track"] = track_new_found_calendars
hass.services.call(DOMAIN, SERVICE_FOUND_CALENDARS, calendar) hass.services.call(DOMAIN, SERVICE_FOUND_CALENDARS, calendar)
@ -339,7 +313,6 @@ def setup_services(
def _add_event(call: ServiceCall) -> None: def _add_event(call: ServiceCall) -> None:
"""Add a new event to calendar.""" """Add a new event to calendar."""
service = calendar_service.get()
start = {} start = {}
end = {} end = {}
@ -374,14 +347,15 @@ def setup_services(
start = {"dateTime": start_dt, "timeZone": str(hass.config.time_zone)} start = {"dateTime": start_dt, "timeZone": str(hass.config.time_zone)}
end = {"dateTime": end_dt, "timeZone": str(hass.config.time_zone)} end = {"dateTime": end_dt, "timeZone": str(hass.config.time_zone)}
event = { calendar_service.create_event(
call.data[EVENT_CALENDAR_ID],
{
"summary": call.data[EVENT_SUMMARY], "summary": call.data[EVENT_SUMMARY],
"description": call.data[EVENT_DESCRIPTION], "description": call.data[EVENT_DESCRIPTION],
"start": start, "start": start,
"end": end, "end": end,
} },
service_data = {"calendarId": call.data[EVENT_CALENDAR_ID], "body": event} )
event = service.events().insert(**service_data).execute()
# Only expose the add event service if we have the correct permissions # Only expose the add event service if we have the correct permissions
if config.get(CONF_CALENDAR_ACCESS) is FeatureAccess.read_write: if config.get(CONF_CALENDAR_ACCESS) is FeatureAccess.read_write:
@ -392,12 +366,11 @@ def setup_services(
def do_setup(hass: HomeAssistant, hass_config: ConfigType, config: ConfigType) -> None: def do_setup(hass: HomeAssistant, hass_config: ConfigType, config: ConfigType) -> None:
"""Run the setup after we have everything configured.""" """Run the setup after we have everything configured."""
_LOGGER.debug("Setting up integration")
# Load calendars the user has configured # Load calendars the user has configured
calendars = load_config(hass.config.path(YAML_DEVICES)) calendars = load_config(hass.config.path(YAML_DEVICES))
hass.data[DOMAIN][DATA_CALENDARS] = calendars hass.data[DOMAIN][DATA_CALENDARS] = calendars
calendar_service = GoogleCalendarService(hass.config.path(TOKEN_FILE)) calendar_service = hass.data[DOMAIN][DATA_SERVICE]
track_new_found_calendars = convert( track_new_found_calendars = convert(
config.get(CONF_TRACK_NEW), bool, DEFAULT_CONF_TRACK_NEW config.get(CONF_TRACK_NEW), bool, DEFAULT_CONF_TRACK_NEW
) )

View File

@ -0,0 +1,86 @@
"""Client library for talking to Google APIs."""
from __future__ import annotations
import datetime
import logging
from typing import Any
from googleapiclient import discovery as google_discovery
from oauth2client.file import Storage
from homeassistant.core import HomeAssistant
from homeassistant.util import dt
_LOGGER = logging.getLogger(__name__)
EVENT_PAGE_SIZE = 100
def _api_time_format(time: datetime.datetime | None) -> str | None:
"""Convert a datetime to the api string format."""
return time.isoformat("T") if time else None
class GoogleCalendarService:
"""Calendar service interface to Google."""
def __init__(self, hass: HomeAssistant, storage: Storage) -> None:
"""Init the Google Calendar service."""
self._hass = hass
self._storage = storage
def _get_service(self) -> google_discovery.Resource:
"""Get the calendar service from the storage file token."""
return google_discovery.build(
"calendar", "v3", credentials=self._storage.get(), cache_discovery=False
)
def list_calendars(self) -> list[dict[str, Any]]:
"""Return the list of calendars the user has added to their list."""
cal_list = self._get_service().calendarList() # pylint: disable=no-member
return cal_list.list().execute()["items"]
def create_event(self, calendar_id: str, event: dict[str, Any]) -> dict[str, Any]:
"""Create an event."""
events = self._get_service().events() # pylint: disable=no-member
return events.insert(calendarId=calendar_id, body=event).execute()
async def async_list_events(
self,
calendar_id: str,
start_time: datetime.datetime | None = None,
end_time: datetime.datetime | None = None,
search: str | None = None,
page_token: str | None = None,
) -> tuple[list[dict[str, Any]], str | None]:
"""Return the list of events."""
return await self._hass.async_add_executor_job(
self.list_events,
calendar_id,
start_time,
end_time,
search,
page_token,
)
def list_events(
self,
calendar_id: str,
start_time: datetime.datetime | None = None,
end_time: datetime.datetime | None = None,
search: str | None = None,
page_token: str | None = None,
) -> tuple[list[dict[str, Any]], str | None]:
"""Return the list of events."""
events = self._get_service().events() # pylint: disable=no-member
result = events.list(
calendarId=calendar_id,
timeMin=_api_time_format(start_time if start_time else dt.now()),
timeMax=_api_time_format(end_time),
q=search,
maxResults=EVENT_PAGE_SIZE,
pageToken=page_token,
).execute()
return (result["items"], result.get("nextPageToken"))

View File

@ -6,7 +6,6 @@ from datetime import datetime, timedelta
import logging import logging
from typing import Any from typing import Any
from googleapiclient import discovery as google_discovery
from httplib2 import ServerNotFoundError from httplib2 import ServerNotFoundError
from homeassistant.components.calendar import ( from homeassistant.components.calendar import (
@ -20,17 +19,18 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import generate_entity_id from homeassistant.helpers.entity import generate_entity_id
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import Throttle, dt from homeassistant.util import Throttle
from . import ( from . import (
CONF_CAL_ID, CONF_CAL_ID,
CONF_IGNORE_AVAILABILITY, CONF_IGNORE_AVAILABILITY,
CONF_SEARCH, CONF_SEARCH,
CONF_TRACK, CONF_TRACK,
DATA_SERVICE,
DEFAULT_CONF_OFFSET, DEFAULT_CONF_OFFSET,
TOKEN_FILE, DOMAIN,
GoogleCalendarService,
) )
from .api import GoogleCalendarService
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -61,7 +61,7 @@ def setup_platform(
if not any(data[CONF_TRACK] for data in disc_info[CONF_ENTITIES]): if not any(data[CONF_TRACK] for data in disc_info[CONF_ENTITIES]):
return return
calendar_service = GoogleCalendarService(hass.config.path(TOKEN_FILE)) calendar_service = hass.data[DOMAIN][DATA_SERVICE]
entities = [] entities = []
for data in disc_info[CONF_ENTITIES]: for data in disc_info[CONF_ENTITIES]:
if not data[CONF_TRACK]: if not data[CONF_TRACK]:
@ -150,23 +150,6 @@ class GoogleCalendarData:
self.ignore_availability = ignore_availability self.ignore_availability = ignore_availability
self.event: dict[str, Any] | None = None self.event: dict[str, Any] | None = None
def _prepare_query(
self,
) -> tuple[google_discovery.Resource | None, dict[str, Any] | None]:
try:
service = self.calendar_service.get()
except ServerNotFoundError as err:
_LOGGER.error("Unable to connect to Google: %s", err)
return None, None
params = dict(DEFAULT_GOOGLE_SEARCH_PARAMS)
params["calendarId"] = self.calendar_id
params["maxResults"] = 100 # Page size
if self.search:
params["q"] = self.search
return service, params
def _event_filter(self, event: dict[str, Any]) -> bool: def _event_filter(self, event: dict[str, Any]) -> bool:
"""Return True if the event is visible.""" """Return True if the event is visible."""
if self.ignore_availability: if self.ignore_availability:
@ -177,51 +160,36 @@ class GoogleCalendarData:
self, hass: HomeAssistant, start_date: datetime, end_date: datetime self, hass: HomeAssistant, start_date: datetime, end_date: datetime
) -> list[dict[str, Any]]: ) -> list[dict[str, Any]]:
"""Get all events in a specific time frame.""" """Get all events in a specific time frame."""
service, params = await hass.async_add_executor_job(self._prepare_query)
if service is None or params is None:
return []
params["timeMin"] = start_date.isoformat("T")
params["timeMax"] = end_date.isoformat("T")
event_list: list[dict[str, Any]] = [] event_list: list[dict[str, Any]] = []
events = await hass.async_add_executor_job(service.events)
page_token: str | None = None page_token: str | None = None
while True: while True:
page_token = await self.async_get_events_page( try:
hass, events, params, page_token, event_list items, page_token = await self.calendar_service.async_list_events(
self.calendar_id,
start_time=start_date,
end_time=end_date,
search=self.search,
page_token=page_token,
) )
except ServerNotFoundError as err:
_LOGGER.error("Unable to connect to Google: %s", err)
return []
event_list.extend(filter(self._event_filter, items))
if not page_token: if not page_token:
break break
return event_list return event_list
async def async_get_events_page(
self,
hass: HomeAssistant,
events: google_discovery.Resource,
params: dict[str, Any],
page_token: str | None,
event_list: list[dict[str, Any]],
) -> str | None:
"""Get a page of events in a specific time frame."""
params["pageToken"] = page_token
result = await hass.async_add_executor_job(events.list(**params).execute)
items = result.get("items", [])
visible_items = filter(self._event_filter, items)
event_list.extend(visible_items)
return result.get("nextPageToken")
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self) -> None: def update(self) -> None:
"""Get the latest data.""" """Get the latest data."""
service, params = self._prepare_query() try:
if service is None or params is None: items, _ = self.calendar_service.list_events(
self.calendar_id, search=self.search
)
except ServerNotFoundError as err:
_LOGGER.error("Unable to connect to Google: %s", err)
return return
params["timeMin"] = dt.now().isoformat("T")
events = service.events()
result = events.list(**params).execute()
items = result.get("items", [])
valid_events = filter(self._event_filter, items) valid_events = filter(self._event_filter, items)
self.event = next(valid_events, None) self.event = next(valid_events, None)

View File

@ -6,10 +6,10 @@ import datetime
from typing import Any, Generator, TypeVar from typing import Any, Generator, TypeVar
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
from googleapiclient import discovery as google_discovery
from oauth2client.client import Credentials, OAuth2Credentials from oauth2client.client import Credentials, OAuth2Credentials
import pytest import pytest
from homeassistant.components.google import GoogleCalendarService
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.util.dt import utcnow from homeassistant.util.dt import utcnow
@ -108,14 +108,21 @@ def mock_next_event():
yield google_cal_data yield google_cal_data
@pytest.fixture(autouse=True)
def calendar_resource() -> YieldFixture[google_discovery.Resource]:
"""Fixture to mock out the Google discovery API."""
with patch("homeassistant.components.google.api.google_discovery.build") as mock:
yield mock
@pytest.fixture @pytest.fixture
def mock_events_list( def mock_events_list(
google_service: GoogleCalendarService, calendar_resource: google_discovery.Resource,
) -> Callable[[dict[str, Any]], None]: ) -> Callable[[dict[str, Any]], None]:
"""Fixture to construct a fake event list API response.""" """Fixture to construct a fake event list API response."""
def _put_result(response: dict[str, Any]) -> None: def _put_result(response: dict[str, Any]) -> None:
google_service.return_value.get.return_value.events.return_value.list.return_value.execute.return_value = ( calendar_resource.return_value.events.return_value.list.return_value.execute.return_value = (
response response
) )
return return
@ -125,12 +132,12 @@ def mock_events_list(
@pytest.fixture @pytest.fixture
def mock_calendars_list( def mock_calendars_list(
google_service: GoogleCalendarService, calendar_resource: google_discovery.Resource,
) -> ApiResult: ) -> ApiResult:
"""Fixture to construct a fake calendar list API response.""" """Fixture to construct a fake calendar list API response."""
def _put_result(response: dict[str, Any]) -> None: def _put_result(response: dict[str, Any]) -> None:
google_service.return_value.get.return_value.calendarList.return_value.list.return_value.execute.return_value = ( calendar_resource.return_value.calendarList.return_value.list.return_value.execute.return_value = (
response response
) )
return return
@ -140,11 +147,9 @@ def mock_calendars_list(
@pytest.fixture @pytest.fixture
def mock_insert_event( def mock_insert_event(
google_service: GoogleCalendarService, calendar_resource: google_discovery.Resource,
) -> Mock: ) -> Mock:
"""Fixture to create a mock to capture new events added to the API.""" """Fixture to create a mock to capture new events added to the API."""
insert_mock = Mock() insert_mock = Mock()
google_service.return_value.get.return_value.events.return_value.insert = ( calendar_resource.return_value.events.return_value.insert = insert_mock
insert_mock
)
return insert_mock return insert_mock

View File

@ -110,17 +110,7 @@ def set_time_zone():
dt_util.set_default_time_zone(dt_util.get_time_zone("UTC")) dt_util.set_default_time_zone(dt_util.get_time_zone("UTC"))
@pytest.fixture(name="google_service") async def test_all_day_event(hass, mock_next_event, mock_token_read):
def mock_google_service():
"""Mock google service."""
patch_google_service = patch(
"homeassistant.components.google.calendar.GoogleCalendarService"
)
with patch_google_service as mock_service:
yield mock_service
async def test_all_day_event(hass, mock_next_event):
"""Test that we can create an event trigger on device.""" """Test that we can create an event trigger on device."""
week_from_today = dt_util.dt.date.today() + dt_util.dt.timedelta(days=7) week_from_today = dt_util.dt.date.today() + dt_util.dt.timedelta(days=7)
end_event = week_from_today + dt_util.dt.timedelta(days=1) end_event = week_from_today + dt_util.dt.timedelta(days=1)
@ -302,9 +292,9 @@ async def test_all_day_offset_event(hass, mock_next_event):
} }
async def test_update_error(hass, google_service): async def test_update_error(hass, calendar_resource):
"""Test that the calendar handles a server error.""" """Test that the calendar handles a server error."""
google_service.return_value.get = Mock( calendar_resource.return_value.get = Mock(
side_effect=httplib2.ServerNotFoundError("unit test") side_effect=httplib2.ServerNotFoundError("unit test")
) )
assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG}) assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG})
@ -315,7 +305,7 @@ async def test_update_error(hass, google_service):
assert state.state == "off" assert state.state == "off"
async def test_calendars_api(hass, hass_client, google_service): async def test_calendars_api(hass, hass_client):
"""Test the Rest API returns the calendar.""" """Test the Rest API returns the calendar."""
assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG}) assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG})
await hass.async_block_till_done() await hass.async_block_till_done()
@ -332,11 +322,9 @@ async def test_calendars_api(hass, hass_client, google_service):
] ]
async def test_http_event_api_failure(hass, hass_client, google_service): async def test_http_event_api_failure(hass, hass_client, calendar_resource):
"""Test the Rest API response during a calendar failure.""" """Test the Rest API response during a calendar failure."""
google_service.return_value.get = Mock( calendar_resource.side_effect = httplib2.ServerNotFoundError("unit test")
side_effect=httplib2.ServerNotFoundError("unit test")
)
assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG}) assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG})
await hass.async_block_till_done() await hass.async_block_till_done()
@ -352,7 +340,7 @@ async def test_http_event_api_failure(hass, hass_client, google_service):
assert events == [] assert events == []
async def test_http_api_event(hass, hass_client, google_service, mock_events_list): async def test_http_api_event(hass, hass_client, mock_events_list):
"""Test querying the API and fetching events from the server.""" """Test querying the API and fetching events from the server."""
now = dt_util.now() now = dt_util.now()
@ -392,7 +380,7 @@ def create_ignore_avail_calendar() -> dict[str, Any]:
@pytest.mark.parametrize("test_calendar", [create_ignore_avail_calendar()]) @pytest.mark.parametrize("test_calendar", [create_ignore_avail_calendar()])
async def test_opaque_event(hass, hass_client, google_service, mock_events_list): async def test_opaque_event(hass, hass_client, mock_events_list):
"""Test querying the API and fetching events from the server.""" """Test querying the API and fetching events from the server."""
now = dt_util.now() now = dt_util.now()
@ -426,7 +414,7 @@ async def test_opaque_event(hass, hass_client, google_service, mock_events_list)
@pytest.mark.parametrize("test_calendar", [create_ignore_avail_calendar()]) @pytest.mark.parametrize("test_calendar", [create_ignore_avail_calendar()])
async def test_transparent_event(hass, hass_client, google_service, mock_events_list): async def test_transparent_event(hass, hass_client, mock_events_list):
"""Test querying the API and fetching events from the server.""" """Test querying the API and fetching events from the server."""
now = dt_util.now() now = dt_util.now()

View File

@ -12,11 +12,7 @@ from oauth2client.client import (
import pytest import pytest
import yaml import yaml
from homeassistant.components.google import ( from homeassistant.components.google import DOMAIN, SERVICE_ADD_EVENT
DOMAIN,
SERVICE_ADD_EVENT,
GoogleCalendarService,
)
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, STATE_OFF from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, STATE_OFF
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
@ -118,15 +114,6 @@ async def component_setup(
return _setup_func return _setup_func
@pytest.fixture
async def google_service() -> YieldFixture[GoogleCalendarService]:
"""Fixture to capture service calls."""
with patch("homeassistant.components.google.GoogleCalendarService") as mock, patch(
"homeassistant.components.google.calendar.GoogleCalendarService", mock
):
yield mock
async def fire_alarm(hass, point_in_time): async def fire_alarm(hass, point_in_time):
"""Fire an alarm and wait for callbacks to run.""" """Fire an alarm and wait for callbacks to run."""
with patch("homeassistant.util.dt.utcnow", return_value=point_in_time): with patch("homeassistant.util.dt.utcnow", return_value=point_in_time):
@ -150,7 +137,6 @@ async def test_setup_config_empty(
async def test_init_success( async def test_init_success(
hass: HomeAssistant, hass: HomeAssistant,
google_service: GoogleCalendarService,
mock_code_flow: Mock, mock_code_flow: Mock,
mock_exchange: Mock, mock_exchange: Mock,
mock_notification: Mock, mock_notification: Mock,
@ -243,7 +229,6 @@ async def test_existing_token(
hass: HomeAssistant, hass: HomeAssistant,
mock_token_read: None, mock_token_read: None,
component_setup: ComponentSetup, component_setup: ComponentSetup,
google_service: GoogleCalendarService,
mock_calendars_yaml: None, mock_calendars_yaml: None,
mock_notification: Mock, mock_notification: Mock,
) -> None: ) -> None:
@ -266,7 +251,6 @@ async def test_existing_token_missing_scope(
token_scopes: list[str], token_scopes: list[str],
mock_token_read: None, mock_token_read: None,
component_setup: ComponentSetup, component_setup: ComponentSetup,
google_service: GoogleCalendarService,
mock_calendars_yaml: None, mock_calendars_yaml: None,
mock_notification: Mock, mock_notification: Mock,
mock_code_flow: Mock, mock_code_flow: Mock,
@ -295,7 +279,6 @@ async def test_calendar_yaml_missing_required_fields(
hass: HomeAssistant, hass: HomeAssistant,
mock_token_read: None, mock_token_read: None,
component_setup: ComponentSetup, component_setup: ComponentSetup,
google_service: GoogleCalendarService,
calendars_config: list[dict[str, Any]], calendars_config: list[dict[str, Any]],
mock_calendars_yaml: None, mock_calendars_yaml: None,
mock_notification: Mock, mock_notification: Mock,
@ -313,7 +296,6 @@ async def test_invalid_calendar_yaml(
hass: HomeAssistant, hass: HomeAssistant,
mock_token_read: None, mock_token_read: None,
component_setup: ComponentSetup, component_setup: ComponentSetup,
google_service: GoogleCalendarService,
calendars_config: list[dict[str, Any]], calendars_config: list[dict[str, Any]],
mock_calendars_yaml: None, mock_calendars_yaml: None,
mock_notification: Mock, mock_notification: Mock,
@ -332,7 +314,6 @@ async def test_found_calendar_from_api(
hass: HomeAssistant, hass: HomeAssistant,
mock_token_read: None, mock_token_read: None,
component_setup: ComponentSetup, component_setup: ComponentSetup,
google_service: GoogleCalendarService,
mock_calendars_list: ApiResult, mock_calendars_list: ApiResult,
test_calendar: dict[str, Any], test_calendar: dict[str, Any],
) -> None: ) -> None:
@ -354,7 +335,6 @@ async def test_add_event(
hass: HomeAssistant, hass: HomeAssistant,
mock_token_read: None, mock_token_read: None,
component_setup: ComponentSetup, component_setup: ComponentSetup,
google_service: GoogleCalendarService,
mock_calendars_list: ApiResult, mock_calendars_list: ApiResult,
test_calendar: dict[str, Any], test_calendar: dict[str, Any],
mock_insert_event: Mock, mock_insert_event: Mock,
@ -416,7 +396,6 @@ async def test_add_event_date_ranges(
mock_token_read: None, mock_token_read: None,
calendars_config: list[dict[str, Any]], calendars_config: list[dict[str, Any]],
component_setup: ComponentSetup, component_setup: ComponentSetup,
google_service: GoogleCalendarService,
mock_calendars_list: ApiResult, mock_calendars_list: ApiResult,
test_calendar: dict[str, Any], test_calendar: dict[str, Any],
mock_insert_event: Mock, mock_insert_event: Mock,