Files

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

190 lines
5.4 KiB
Python
Raw Permalink Normal View History

"""Test fitbit component."""
from collections.abc import Awaitable, Callable
from http import HTTPStatus
import pytest
from homeassistant.components.fitbit.const import (
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
OAUTH2_TOKEN,
)
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from .conftest import (
CLIENT_ID,
CLIENT_SECRET,
DEVICES_API_URL,
FAKE_ACCESS_TOKEN,
FAKE_REFRESH_TOKEN,
SERVER_ACCESS_TOKEN,
)
from tests.common import MockConfigEntry
from tests.test_util.aiohttp import AiohttpClientMocker
async def test_setup(
hass: HomeAssistant,
integration_setup: Callable[[], Awaitable[bool]],
config_entry: MockConfigEntry,
setup_credentials: None,
) -> None:
"""Test setting up the integration."""
assert config_entry.state is ConfigEntryState.NOT_LOADED
assert await integration_setup()
assert config_entry.state is ConfigEntryState.LOADED
assert await hass.config_entries.async_unload(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.NOT_LOADED
@pytest.mark.parametrize(
("token_expiration_time", "server_status"),
[
(12345, HTTPStatus.INTERNAL_SERVER_ERROR),
(12345, HTTPStatus.FORBIDDEN),
(12345, HTTPStatus.NOT_FOUND),
],
)
async def test_token_refresh_failure(
integration_setup: Callable[[], Awaitable[bool]],
config_entry: MockConfigEntry,
aioclient_mock: AiohttpClientMocker,
setup_credentials: None,
server_status: HTTPStatus,
) -> None:
"""Test where token is expired and the refresh attempt fails and will be retried."""
aioclient_mock.post(
OAUTH2_TOKEN,
status=server_status,
)
assert not await integration_setup()
assert config_entry.state is ConfigEntryState.SETUP_RETRY
@pytest.mark.parametrize("token_expiration_time", [12345])
async def test_token_refresh_success(
integration_setup: Callable[[], Awaitable[bool]],
config_entry: MockConfigEntry,
aioclient_mock: AiohttpClientMocker,
setup_credentials: None,
) -> None:
"""Test where token is expired and the refresh attempt succeeds."""
assert config_entry.data["token"]["access_token"] == FAKE_ACCESS_TOKEN
aioclient_mock.post(
OAUTH2_TOKEN,
json=SERVER_ACCESS_TOKEN,
)
assert await integration_setup()
assert config_entry.state is ConfigEntryState.LOADED
# Verify token request and that the device API is called with new token
assert len(aioclient_mock.mock_calls) == 2
assert aioclient_mock.mock_calls[0][2] == {
CONF_CLIENT_ID: CLIENT_ID,
CONF_CLIENT_SECRET: CLIENT_SECRET,
"grant_type": "refresh_token",
"refresh_token": FAKE_REFRESH_TOKEN,
}
assert str(aioclient_mock.mock_calls[1][1]) == DEVICES_API_URL
assert aioclient_mock.mock_calls[1][3].get("Authorization") == (
"Bearer server-access-token"
)
# Verify updated token
assert (
config_entry.data["token"]["access_token"]
== SERVER_ACCESS_TOKEN["access_token"]
)
@pytest.mark.parametrize(
("token_expiration_time", "server_status"),
[
(12345, HTTPStatus.UNAUTHORIZED),
(12345, HTTPStatus.BAD_REQUEST),
],
)
@pytest.mark.parametrize("closing", [True, False])
async def test_token_requires_reauth(
hass: HomeAssistant,
integration_setup: Callable[[], Awaitable[bool]],
config_entry: MockConfigEntry,
aioclient_mock: AiohttpClientMocker,
setup_credentials: None,
server_status: HTTPStatus,
closing: bool,
) -> None:
"""Test where token is expired and the refresh attempt requires reauth."""
aioclient_mock.post(
OAUTH2_TOKEN,
status=server_status,
closing=closing,
)
assert not await integration_setup()
assert config_entry.state is ConfigEntryState.SETUP_ERROR
flows = hass.config_entries.flow.async_progress()
assert len(flows) == 1
assert flows[0]["step_id"] == "reauth_confirm"
async def test_device_update_coordinator_failure(
hass: HomeAssistant,
integration_setup: Callable[[], Awaitable[bool]],
config_entry: MockConfigEntry,
setup_credentials: None,
aioclient_mock: AiohttpClientMocker,
) -> None:
"""Test case where the device update coordinator fails on the first request."""
assert config_entry.state is ConfigEntryState.NOT_LOADED
aioclient_mock.clear_requests()
aioclient_mock.get(
DEVICES_API_URL,
status=HTTPStatus.INTERNAL_SERVER_ERROR,
)
assert not await integration_setup()
assert config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_device_update_coordinator_reauth(
hass: HomeAssistant,
integration_setup: Callable[[], Awaitable[bool]],
config_entry: MockConfigEntry,
setup_credentials: None,
aioclient_mock: AiohttpClientMocker,
) -> None:
"""Test case where the device update coordinator fails on the first request."""
assert config_entry.state is ConfigEntryState.NOT_LOADED
aioclient_mock.clear_requests()
aioclient_mock.get(
DEVICES_API_URL,
status=HTTPStatus.UNAUTHORIZED,
json={
"errors": [{"errorType": "invalid_grant"}],
},
)
assert not await integration_setup()
assert config_entry.state is ConfigEntryState.SETUP_ERROR
flows = hass.config_entries.flow.async_progress()
assert len(flows) == 1
assert flows[0]["step_id"] == "reauth_confirm"