From 466f1686e4409622daa5b973da9d44e9e2b955bf Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Sun, 27 Feb 2022 10:58:00 -0800 Subject: [PATCH] Cleanup google calendar shared test fixtures (#67343) --- tests/components/google/conftest.py | 23 +-- tests/components/google/test_calendar.py | 217 ++++++++++------------- 2 files changed, 102 insertions(+), 138 deletions(-) diff --git a/tests/components/google/conftest.py b/tests/components/google/conftest.py index b78f97e8209..f224f3f2f31 100644 --- a/tests/components/google/conftest.py +++ b/tests/components/google/conftest.py @@ -98,16 +98,6 @@ async def mock_token_read( 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(autouse=True) def calendar_resource() -> YieldFixture[google_discovery.Resource]: """Fixture to mock out the Google discovery API.""" @@ -130,6 +120,19 @@ def mock_events_list( return _put_result +@pytest.fixture +def mock_events_list_items( + mock_events_list: Callable[[dict[str, Any]], None] +) -> Callable[list[[dict[str, Any]]], None]: + """Fixture to construct an API response containing event items.""" + + def _put_items(items: list[dict[str, Any]]) -> None: + mock_events_list({"items": items}) + return + + return _put_items + + @pytest.fixture def mock_calendars_list( calendar_resource: google_discovery.Resource, diff --git a/tests/components/google/test_calendar.py b/tests/components/google/test_calendar.py index 80cf9c3d67d..dda30a1d83e 100644 --- a/tests/components/google/test_calendar.py +++ b/tests/components/google/test_calendar.py @@ -2,7 +2,6 @@ from __future__ import annotations -import copy from http import HTTPStatus from typing import Any from unittest.mock import Mock, patch @@ -110,16 +109,33 @@ def set_time_zone(): dt_util.set_default_time_zone(dt_util.get_time_zone("UTC")) -async def test_all_day_event(hass, mock_next_event, mock_token_read): +def upcoming() -> dict[str, Any]: + """Create a test event with an arbitrary start/end time fetched from the api url.""" + now = dt_util.now() + return { + "start": {"dateTime": now.isoformat()}, + "end": {"dateTime": (now + dt_util.dt.timedelta(minutes=5)).isoformat()}, + } + + +def upcoming_event_url() -> str: + """Return a calendar API to return events created by upcoming().""" + now = dt_util.now() + start = (now - dt_util.dt.timedelta(minutes=60)).isoformat() + end = (now + dt_util.dt.timedelta(minutes=60)).isoformat() + return f"/api/calendars/{TEST_ENTITY}?start={start}&end={end}" + + +async def test_all_day_event(hass, mock_events_list_items, mock_token_read): """Test that we can create an event trigger on device.""" 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) - event = copy.deepcopy(TEST_EVENT) - start = week_from_today.isoformat() - end = end_event.isoformat() - event["start"]["date"] = start - event["end"]["date"] = end - mock_next_event.return_value.event = event + event = { + **TEST_EVENT, + "start": {"date": week_from_today.isoformat()}, + "end": {"date": end_event.isoformat()}, + } + mock_events_list_items([event]) assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG}) await hass.async_block_till_done() @@ -139,16 +155,16 @@ async def test_all_day_event(hass, mock_next_event, mock_token_read): } -async def test_future_event(hass, mock_next_event): +async def test_future_event(hass, mock_events_list_items): """Test that we can create an event trigger on device.""" one_hour_from_now = dt_util.now() + dt_util.dt.timedelta(minutes=30) end_event = one_hour_from_now + dt_util.dt.timedelta(minutes=60) - start = one_hour_from_now.isoformat() - end = end_event.isoformat() - event = copy.deepcopy(TEST_EVENT) - event["start"]["dateTime"] = start - event["end"]["dateTime"] = end - mock_next_event.return_value.event = event + event = { + **TEST_EVENT, + "start": {"dateTime": one_hour_from_now.isoformat()}, + "end": {"dateTime": end_event.isoformat()}, + } + mock_events_list_items([event]) assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG}) await hass.async_block_till_done() @@ -168,16 +184,16 @@ async def test_future_event(hass, mock_next_event): } -async def test_in_progress_event(hass, mock_next_event): +async def test_in_progress_event(hass, mock_events_list_items): """Test that we can create an event trigger on device.""" middle_of_event = dt_util.now() - dt_util.dt.timedelta(minutes=30) end_event = middle_of_event + dt_util.dt.timedelta(minutes=60) - start = middle_of_event.isoformat() - end = end_event.isoformat() - event = copy.deepcopy(TEST_EVENT) - event["start"]["dateTime"] = start - event["end"]["dateTime"] = end - mock_next_event.return_value.event = event + event = { + **TEST_EVENT, + "start": {"dateTime": middle_of_event.isoformat()}, + "end": {"dateTime": end_event.isoformat()}, + } + mock_events_list_items([event]) assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG}) await hass.async_block_till_done() @@ -197,18 +213,18 @@ async def test_in_progress_event(hass, mock_next_event): } -async def test_offset_in_progress_event(hass, mock_next_event): +async def test_offset_in_progress_event(hass, mock_events_list_items): """Test that we can create an event trigger on device.""" middle_of_event = dt_util.now() + dt_util.dt.timedelta(minutes=14) end_event = middle_of_event + dt_util.dt.timedelta(minutes=60) - start = middle_of_event.isoformat() - end = end_event.isoformat() event_summary = "Test Event in Progress" - event = copy.deepcopy(TEST_EVENT) - event["start"]["dateTime"] = start - event["end"]["dateTime"] = end - event["summary"] = f"{event_summary} !!-15" - mock_next_event.return_value.event = event + event = { + **TEST_EVENT, + "start": {"dateTime": middle_of_event.isoformat()}, + "end": {"dateTime": end_event.isoformat()}, + "summary": f"{event_summary} !!-15", + } + mock_events_list_items([event]) assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG}) await hass.async_block_till_done() @@ -229,18 +245,18 @@ async def test_offset_in_progress_event(hass, mock_next_event): @pytest.mark.skip -async def test_all_day_offset_in_progress_event(hass, mock_next_event): +async def test_all_day_offset_in_progress_event(hass, mock_events_list_items): """Test that we can create an event trigger on device.""" tomorrow = dt_util.dt.date.today() + dt_util.dt.timedelta(days=1) end_event = tomorrow + dt_util.dt.timedelta(days=1) - start = tomorrow.isoformat() - end = end_event.isoformat() event_summary = "Test All Day Event Offset In Progress" - event = copy.deepcopy(TEST_EVENT) - event["start"]["date"] = start - event["end"]["date"] = end - event["summary"] = f"{event_summary} !!-25:0" - mock_next_event.return_value.event = event + event = { + **TEST_EVENT, + "start": {"date": tomorrow.isoformat()}, + "end": {"date": end_event.isoformat()}, + "summary": f"{event_summary} !!-25:0", + } + mock_events_list_items([event]) assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG}) await hass.async_block_till_done() @@ -260,19 +276,19 @@ async def test_all_day_offset_in_progress_event(hass, mock_next_event): } -async def test_all_day_offset_event(hass, mock_next_event): +async def test_all_day_offset_event(hass, mock_events_list_items): """Test that we can create an event trigger on device.""" tomorrow = dt_util.dt.date.today() + dt_util.dt.timedelta(days=2) end_event = tomorrow + dt_util.dt.timedelta(days=1) - start = tomorrow.isoformat() - end = end_event.isoformat() offset_hours = 1 + dt_util.now().hour event_summary = "Test All Day Event Offset" - event = copy.deepcopy(TEST_EVENT) - event["start"]["date"] = start - event["end"]["date"] = end - event["summary"] = f"{event_summary} !!-{offset_hours}:0" - mock_next_event.return_value.event = event + event = { + **TEST_EVENT, + "start": {"date": tomorrow.isoformat()}, + "end": {"date": end_event.isoformat()}, + "summary": f"{event_summary} !!-{offset_hours}:0", + } + mock_events_list_items([event]) assert await async_setup_component(hass, "google", {"google": GOOGLE_CONFIG}) await hass.async_block_till_done() @@ -329,47 +345,31 @@ async def test_http_event_api_failure(hass, hass_client, calendar_resource): 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}") + response = await client.get(upcoming_event_url()) 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 == [] -async def test_http_api_event(hass, hass_client, mock_events_list): +async def test_http_api_event(hass, hass_client, mock_events_list_items): """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() - }, - } - ], - } - ) + event = { + **TEST_EVENT, + **upcoming(), + } + mock_events_list_items([event]) 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}") + response = await client.get(upcoming_event_url()) assert response.status == HTTPStatus.OK events = await response.json() assert len(events) == 1 assert "summary" in events[0] - assert events[0]["summary"] == "Event title" + assert events[0]["summary"] == event["summary"] def create_ignore_avail_calendar() -> dict[str, Any]: @@ -379,67 +379,28 @@ def create_ignore_avail_calendar() -> dict[str, Any]: return calendar -@pytest.mark.parametrize("test_calendar", [create_ignore_avail_calendar()]) -async def test_opaque_event(hass, hass_client, mock_events_list): +@pytest.mark.parametrize( + "test_calendar,transparency,expect_visible_event", + [ + (create_ignore_avail_calendar(), "opaque", True), + (create_ignore_avail_calendar(), "transparent", False), + ], +) +async def test_opaque_event( + hass, hass_client, mock_events_list_items, transparency, expect_visible_event +): """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() - }, - } - ], - } - ) + event = { + **TEST_EVENT, + **upcoming(), + "transparency": transparency, + } + mock_events_list_items([event]) 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}") + response = await client.get(upcoming_event_url()) 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, 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 == [] + assert (len(events) > 0) == expect_visible_event