core/tests/components/google_tasks/test_init.py

155 lines
4.4 KiB
Python

"""Tests for Google Tasks."""
from collections.abc import Awaitable, Callable
import http
from http import HTTPStatus
import json
import time
from unittest.mock import Mock
from aiohttp import ClientError
from httplib2 import Response
import pytest
from homeassistant.components.google_tasks import DOMAIN
from homeassistant.components.google_tasks.const import OAUTH2_TOKEN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from .conftest import LIST_TASK_LIST_RESPONSE, LIST_TASKS_RESPONSE_WATER
from tests.common import MockConfigEntry
from tests.test_util.aiohttp import AiohttpClientMocker
@pytest.mark.parametrize(
"api_responses", [[LIST_TASK_LIST_RESPONSE, LIST_TASKS_RESPONSE_WATER]]
)
async def test_setup(
hass: HomeAssistant,
integration_setup: Callable[[], Awaitable[bool]],
config_entry: MockConfigEntry,
setup_credentials: None,
mock_http_response: Mock,
) -> None:
"""Test successful setup and unload."""
assert config_entry.state is ConfigEntryState.NOT_LOADED
await integration_setup()
assert config_entry.state is ConfigEntryState.LOADED
await hass.config_entries.async_unload(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.NOT_LOADED
assert not hass.services.async_services().get(DOMAIN)
@pytest.mark.parametrize("expires_at", [time.time() - 86400], ids=["expired"])
@pytest.mark.parametrize(
"api_responses", [[LIST_TASK_LIST_RESPONSE, LIST_TASKS_RESPONSE_WATER]]
)
async def test_expired_token_refresh_success(
hass: HomeAssistant,
integration_setup: Callable[[], Awaitable[bool]],
aioclient_mock: AiohttpClientMocker,
config_entry: MockConfigEntry,
setup_credentials: None,
mock_http_response: Mock,
) -> None:
"""Test expired token is refreshed."""
aioclient_mock.clear_requests()
aioclient_mock.post(
OAUTH2_TOKEN,
json={
"access_token": "updated-access-token",
"refresh_token": "updated-refresh-token",
"expires_at": time.time() + 86400,
"expires_in": 86400,
},
)
await integration_setup()
assert config_entry.state is ConfigEntryState.LOADED
assert config_entry.data["token"]["access_token"] == "updated-access-token"
assert config_entry.data["token"]["expires_in"] == 86400
@pytest.mark.parametrize(
("expires_at", "status", "exc", "expected_state"),
[
(
time.time() - 86400,
http.HTTPStatus.UNAUTHORIZED,
None,
ConfigEntryState.SETUP_ERROR,
),
(
time.time() - 86400,
http.HTTPStatus.INTERNAL_SERVER_ERROR,
None,
ConfigEntryState.SETUP_RETRY,
),
(
time.time() - 86400,
None,
ClientError("error"),
ConfigEntryState.SETUP_RETRY,
),
],
ids=["unauthorized", "internal_server_error", "client_error"],
)
async def test_expired_token_refresh_failure(
hass: HomeAssistant,
integration_setup: Callable[[], Awaitable[bool]],
aioclient_mock: AiohttpClientMocker,
config_entry: MockConfigEntry,
setup_credentials: None,
status: http.HTTPStatus | None,
exc: Exception | None,
expected_state: ConfigEntryState,
) -> None:
"""Test failure while refreshing token with a transient error."""
aioclient_mock.clear_requests()
aioclient_mock.post(
OAUTH2_TOKEN,
status=status,
exc=exc,
)
await integration_setup()
assert config_entry.state is expected_state
@pytest.mark.parametrize(
"response_handler",
[
([(Response({"status": HTTPStatus.INTERNAL_SERVER_ERROR}), b"")]),
# First request succeeds, second request fails
(
[
(
Response({"status": HTTPStatus.OK}),
json.dumps(LIST_TASK_LIST_RESPONSE),
),
(Response({"status": HTTPStatus.INTERNAL_SERVER_ERROR}), b""),
]
),
],
)
async def test_setup_error(
hass: HomeAssistant,
setup_credentials: None,
integration_setup: Callable[[], Awaitable[bool]],
mock_http_response: Mock,
config_entry: MockConfigEntry,
) -> None:
"""Test an error returned by the server when setting up the platform."""
assert not await integration_setup()
assert config_entry.state is ConfigEntryState.SETUP_RETRY