Remove code for old fitbit config import (#130783)
* Remove code for old fitbit config import * Remove translations related to issuespull/130719/head
parent
f58b5418ea
commit
96299b16e2
|
@ -6,30 +6,16 @@ from collections.abc import Callable
|
|||
from dataclasses import dataclass
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, Final, cast
|
||||
|
||||
from fitbit import Fitbit
|
||||
from oauthlib.oauth2.rfc6749.errors import OAuth2Error
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.application_credentials import (
|
||||
ClientCredential,
|
||||
async_import_client_credential,
|
||||
)
|
||||
from homeassistant.components.sensor import (
|
||||
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorEntityDescription,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_CLIENT_ID,
|
||||
CONF_CLIENT_SECRET,
|
||||
CONF_TOKEN,
|
||||
CONF_UNIT_SYSTEM,
|
||||
PERCENTAGE,
|
||||
EntityCategory,
|
||||
UnitOfLength,
|
||||
|
@ -38,33 +24,13 @@ from homeassistant.const import (
|
|||
UnitOfVolume,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.icon import icon_for_battery_level
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
from homeassistant.util.json import load_json_object
|
||||
|
||||
from .api import FitbitApi
|
||||
from .const import (
|
||||
ATTR_ACCESS_TOKEN,
|
||||
ATTR_LAST_SAVED_AT,
|
||||
ATTR_REFRESH_TOKEN,
|
||||
ATTRIBUTION,
|
||||
BATTERY_LEVELS,
|
||||
CONF_CLOCK_FORMAT,
|
||||
CONF_MONITORED_RESOURCES,
|
||||
DEFAULT_CLOCK_FORMAT,
|
||||
DEFAULT_CONFIG,
|
||||
DOMAIN,
|
||||
FITBIT_CONFIG_FILE,
|
||||
FITBIT_DEFAULT_RESOURCES,
|
||||
FitbitScope,
|
||||
FitbitUnitSystem,
|
||||
)
|
||||
from .const import ATTRIBUTION, BATTERY_LEVELS, DOMAIN, FitbitScope, FitbitUnitSystem
|
||||
from .coordinator import FitbitData, FitbitDeviceCoordinator
|
||||
from .exceptions import FitbitApiException, FitbitAuthException
|
||||
from .model import FitbitDevice, config_from_entry_data
|
||||
|
@ -533,126 +499,6 @@ FITBIT_RESOURCE_BATTERY_LEVEL = FitbitSensorEntityDescription(
|
|||
native_unit_of_measurement=PERCENTAGE,
|
||||
)
|
||||
|
||||
FITBIT_RESOURCES_KEYS: Final[list[str]] = [
|
||||
desc.key
|
||||
for desc in (*FITBIT_RESOURCES_LIST, FITBIT_RESOURCE_BATTERY, SLEEP_START_TIME)
|
||||
]
|
||||
|
||||
PLATFORM_SCHEMA: Final = SENSOR_PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Optional(
|
||||
CONF_MONITORED_RESOURCES, default=FITBIT_DEFAULT_RESOURCES
|
||||
): vol.All(cv.ensure_list, [vol.In(FITBIT_RESOURCES_KEYS)]),
|
||||
vol.Optional(CONF_CLOCK_FORMAT, default=DEFAULT_CLOCK_FORMAT): vol.In(
|
||||
["12H", "24H"]
|
||||
),
|
||||
vol.Optional(CONF_UNIT_SYSTEM, default=FitbitUnitSystem.LEGACY_DEFAULT): vol.In(
|
||||
[
|
||||
FitbitUnitSystem.EN_GB,
|
||||
FitbitUnitSystem.EN_US,
|
||||
FitbitUnitSystem.METRIC,
|
||||
FitbitUnitSystem.LEGACY_DEFAULT,
|
||||
]
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
# Only import configuration if it was previously created successfully with all
|
||||
# of the following fields.
|
||||
FITBIT_CONF_KEYS = [
|
||||
CONF_CLIENT_ID,
|
||||
CONF_CLIENT_SECRET,
|
||||
ATTR_ACCESS_TOKEN,
|
||||
ATTR_REFRESH_TOKEN,
|
||||
ATTR_LAST_SAVED_AT,
|
||||
]
|
||||
|
||||
|
||||
def load_config_file(config_path: str) -> dict[str, Any] | None:
|
||||
"""Load existing valid fitbit.conf from disk for import."""
|
||||
if os.path.isfile(config_path):
|
||||
config_file = load_json_object(config_path)
|
||||
if config_file != DEFAULT_CONFIG and all(
|
||||
key in config_file for key in FITBIT_CONF_KEYS
|
||||
):
|
||||
return config_file
|
||||
return None
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
add_entities: AddEntitiesCallback,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the Fitbit sensor."""
|
||||
config_path = hass.config.path(FITBIT_CONFIG_FILE)
|
||||
config_file = await hass.async_add_executor_job(load_config_file, config_path)
|
||||
_LOGGER.debug("loaded config file: %s", config_file)
|
||||
|
||||
if config_file is not None:
|
||||
_LOGGER.debug("Importing existing fitbit.conf application credentials")
|
||||
|
||||
# Refresh the token before importing to ensure it is working and not
|
||||
# expired on first initialization.
|
||||
authd_client = Fitbit(
|
||||
config_file[CONF_CLIENT_ID],
|
||||
config_file[CONF_CLIENT_SECRET],
|
||||
access_token=config_file[ATTR_ACCESS_TOKEN],
|
||||
refresh_token=config_file[ATTR_REFRESH_TOKEN],
|
||||
expires_at=config_file[ATTR_LAST_SAVED_AT],
|
||||
refresh_cb=lambda x: None,
|
||||
)
|
||||
try:
|
||||
updated_token = await hass.async_add_executor_job(
|
||||
authd_client.client.refresh_token
|
||||
)
|
||||
except OAuth2Error as err:
|
||||
_LOGGER.debug("Unable to import fitbit OAuth2 credentials: %s", err)
|
||||
translation_key = "deprecated_yaml_import_issue_cannot_connect"
|
||||
else:
|
||||
await async_import_client_credential(
|
||||
hass,
|
||||
DOMAIN,
|
||||
ClientCredential(
|
||||
config_file[CONF_CLIENT_ID], config_file[CONF_CLIENT_SECRET]
|
||||
),
|
||||
)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_IMPORT},
|
||||
data={
|
||||
"auth_implementation": DOMAIN,
|
||||
CONF_TOKEN: {
|
||||
ATTR_ACCESS_TOKEN: updated_token[ATTR_ACCESS_TOKEN],
|
||||
ATTR_REFRESH_TOKEN: updated_token[ATTR_REFRESH_TOKEN],
|
||||
"expires_at": updated_token["expires_at"],
|
||||
"scope": " ".join(updated_token.get("scope", [])),
|
||||
},
|
||||
CONF_CLOCK_FORMAT: config[CONF_CLOCK_FORMAT],
|
||||
CONF_UNIT_SYSTEM: config[CONF_UNIT_SYSTEM],
|
||||
CONF_MONITORED_RESOURCES: config[CONF_MONITORED_RESOURCES],
|
||||
},
|
||||
)
|
||||
translation_key = "deprecated_yaml_import"
|
||||
if (
|
||||
result.get("type") == FlowResultType.ABORT
|
||||
and result.get("reason") == "cannot_connect"
|
||||
):
|
||||
translation_key = "deprecated_yaml_import_issue_cannot_connect"
|
||||
else:
|
||||
translation_key = "deprecated_yaml_no_import"
|
||||
|
||||
async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"deprecated_yaml",
|
||||
breaks_in_ha_version="2024.5.0",
|
||||
is_fixable=False,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key=translation_key,
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
|
|
|
@ -40,19 +40,5 @@
|
|||
"name": "Battery level"
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"deprecated_yaml_no_import": {
|
||||
"title": "Fitbit YAML configuration is being removed",
|
||||
"description": "Configuring Fitbit using YAML is being removed.\n\nRemove the `fitbit` configuration from your configuration.yaml file and remove fitbit.conf if it exists and restart Home Assistant and [set up the integration](/config/integrations/dashboard/add?domain=fitbit) manually."
|
||||
},
|
||||
"deprecated_yaml_import": {
|
||||
"title": "Fitbit YAML configuration is being removed",
|
||||
"description": "Configuring Fitbit using YAML is being removed.\n\nYour existing YAML configuration has been imported into the UI automatically, including OAuth Application Credentials.\n\nRemove the `fitbit` configuration from your configuration.yaml file and remove fitbit.conf and restart Home Assistant to fix this issue."
|
||||
},
|
||||
"deprecated_yaml_import_issue_cannot_connect": {
|
||||
"title": "The Fitbit YAML configuration import failed",
|
||||
"description": "Configuring Fitbit using YAML is being removed but there was a connection error importing your YAML configuration.\n\nRestart Home Assistant to try again or remove the Fitbit YAML configuration from your configuration.yaml file and remove the fitbit.conf and continue to [set up the integration](/config/integrations/dashboard/add?domain=fitbit) manually."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Test fixtures for fitbit."""
|
||||
|
||||
from collections.abc import Awaitable, Callable, Generator
|
||||
from collections.abc import Awaitable, Callable
|
||||
import datetime
|
||||
from http import HTTPStatus
|
||||
import time
|
||||
|
@ -14,12 +14,7 @@ from homeassistant.components.application_credentials import (
|
|||
ClientCredential,
|
||||
async_import_client_credential,
|
||||
)
|
||||
from homeassistant.components.fitbit.const import (
|
||||
CONF_CLIENT_ID,
|
||||
CONF_CLIENT_SECRET,
|
||||
DOMAIN,
|
||||
OAUTH_SCOPES,
|
||||
)
|
||||
from homeassistant.components.fitbit.const import DOMAIN, OAUTH_SCOPES
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
@ -83,13 +78,16 @@ def mock_token_entry(token_expiration_time: float, scopes: list[str]) -> dict[st
|
|||
|
||||
|
||||
@pytest.fixture(name="config_entry")
|
||||
def mock_config_entry(token_entry: dict[str, Any]) -> MockConfigEntry:
|
||||
def mock_config_entry(
|
||||
token_entry: dict[str, Any], imported_config_data: dict[str, Any]
|
||||
) -> MockConfigEntry:
|
||||
"""Fixture for a config entry."""
|
||||
return MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
"auth_implementation": FAKE_AUTH_IMPL,
|
||||
"token": token_entry,
|
||||
**imported_config_data,
|
||||
},
|
||||
unique_id=PROFILE_USER_ID,
|
||||
)
|
||||
|
@ -107,37 +105,6 @@ async def setup_credentials(hass: HomeAssistant) -> None:
|
|||
)
|
||||
|
||||
|
||||
@pytest.fixture(name="fitbit_config_yaml")
|
||||
def mock_fitbit_config_yaml(token_expiration_time: float) -> dict[str, Any] | None:
|
||||
"""Fixture for the yaml fitbit.conf file contents."""
|
||||
return {
|
||||
CONF_CLIENT_ID: CLIENT_ID,
|
||||
CONF_CLIENT_SECRET: CLIENT_SECRET,
|
||||
"access_token": FAKE_ACCESS_TOKEN,
|
||||
"refresh_token": FAKE_REFRESH_TOKEN,
|
||||
"last_saved_at": token_expiration_time,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(name="fitbit_config_setup")
|
||||
def mock_fitbit_config_setup(
|
||||
fitbit_config_yaml: dict[str, Any] | None,
|
||||
) -> Generator[None]:
|
||||
"""Fixture to mock out fitbit.conf file data loading and persistence."""
|
||||
has_config = fitbit_config_yaml is not None
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.fitbit.sensor.os.path.isfile",
|
||||
return_value=has_config,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.fitbit.sensor.load_json_object",
|
||||
return_value=fitbit_config_yaml,
|
||||
),
|
||||
):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(name="monitored_resources")
|
||||
def mock_monitored_resources() -> list[str] | None:
|
||||
"""Fixture for the fitbit yaml config monitored_resources field."""
|
||||
|
@ -150,8 +117,8 @@ def mock_configured_unit_syststem() -> str | None:
|
|||
return None
|
||||
|
||||
|
||||
@pytest.fixture(name="sensor_platform_config")
|
||||
def mock_sensor_platform_config(
|
||||
@pytest.fixture(name="imported_config_data")
|
||||
def mock_imported_config_data(
|
||||
monitored_resources: list[str] | None,
|
||||
configured_unit_system: str | None,
|
||||
) -> dict[str, Any]:
|
||||
|
@ -164,32 +131,6 @@ def mock_sensor_platform_config(
|
|||
return config
|
||||
|
||||
|
||||
@pytest.fixture(name="sensor_platform_setup")
|
||||
async def mock_sensor_platform_setup(
|
||||
hass: HomeAssistant,
|
||||
sensor_platform_config: dict[str, Any],
|
||||
) -> Callable[[], Awaitable[bool]]:
|
||||
"""Fixture to set up the integration."""
|
||||
|
||||
async def run() -> bool:
|
||||
result = await async_setup_component(
|
||||
hass,
|
||||
"sensor",
|
||||
{
|
||||
"sensor": [
|
||||
{
|
||||
"platform": DOMAIN,
|
||||
**sensor_platform_config,
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
return result
|
||||
|
||||
return run
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def platforms() -> list[Platform]:
|
||||
"""Fixture to specify platforms to test."""
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from http import HTTPStatus
|
||||
import time
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
|
@ -13,7 +12,7 @@ from homeassistant import config_entries
|
|||
from homeassistant.components.fitbit.const import DOMAIN, OAUTH2_AUTHORIZE, OAUTH2_TOKEN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
from homeassistant.helpers import config_entry_oauth2_flow, issue_registry as ir
|
||||
from homeassistant.helpers import config_entry_oauth2_flow
|
||||
|
||||
from .conftest import (
|
||||
CLIENT_ID,
|
||||
|
@ -255,207 +254,6 @@ async def test_config_entry_already_exists(
|
|||
assert result.get("reason") == "already_configured"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"token_expiration_time",
|
||||
[time.time() + 86400, time.time() - 86400],
|
||||
ids=("token_active", "token_expired"),
|
||||
)
|
||||
async def test_import_fitbit_config(
|
||||
hass: HomeAssistant,
|
||||
fitbit_config_setup: None,
|
||||
sensor_platform_setup: Callable[[], Awaitable[bool]],
|
||||
issue_registry: ir.IssueRegistry,
|
||||
requests_mock: Mocker,
|
||||
) -> None:
|
||||
"""Test that platform configuration is imported successfully."""
|
||||
|
||||
requests_mock.register_uri(
|
||||
"POST",
|
||||
OAUTH2_TOKEN,
|
||||
status_code=HTTPStatus.OK,
|
||||
json=SERVER_ACCESS_TOKEN,
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.fitbit.async_setup_entry", return_value=True
|
||||
) as mock_setup:
|
||||
await sensor_platform_setup()
|
||||
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
|
||||
# Verify valid profile can be fetched from the API
|
||||
config_entry = entries[0]
|
||||
assert config_entry.title == DISPLAY_NAME
|
||||
assert config_entry.unique_id == PROFILE_USER_ID
|
||||
|
||||
data = dict(config_entry.data)
|
||||
# Verify imported values from fitbit.conf and configuration.yaml and
|
||||
# that the token is updated.
|
||||
assert "token" in data
|
||||
expires_at = data["token"]["expires_at"]
|
||||
assert expires_at > time.time()
|
||||
del data["token"]["expires_at"]
|
||||
assert dict(config_entry.data) == {
|
||||
"auth_implementation": DOMAIN,
|
||||
"clock_format": "24H",
|
||||
"monitored_resources": ["activities/steps"],
|
||||
"token": {
|
||||
"access_token": "server-access-token",
|
||||
"refresh_token": "server-refresh-token",
|
||||
"scope": "activity heartrate nutrition profile settings sleep weight",
|
||||
},
|
||||
"unit_system": "default",
|
||||
}
|
||||
|
||||
# Verify an issue is raised for deprecated configuration.yaml
|
||||
issue = issue_registry.issues.get((DOMAIN, "deprecated_yaml"))
|
||||
assert issue
|
||||
assert issue.translation_key == "deprecated_yaml_import"
|
||||
|
||||
|
||||
async def test_import_fitbit_config_failure_cannot_connect(
|
||||
hass: HomeAssistant,
|
||||
fitbit_config_setup: None,
|
||||
sensor_platform_setup: Callable[[], Awaitable[bool]],
|
||||
issue_registry: ir.IssueRegistry,
|
||||
requests_mock: Mocker,
|
||||
) -> None:
|
||||
"""Test platform configuration fails to import successfully."""
|
||||
|
||||
requests_mock.register_uri(
|
||||
"POST",
|
||||
OAUTH2_TOKEN,
|
||||
status_code=HTTPStatus.OK,
|
||||
json=SERVER_ACCESS_TOKEN,
|
||||
)
|
||||
requests_mock.register_uri(
|
||||
"GET", PROFILE_API_URL, status_code=HTTPStatus.INTERNAL_SERVER_ERROR
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.fitbit.async_setup_entry", return_value=True
|
||||
) as mock_setup:
|
||||
await sensor_platform_setup()
|
||||
|
||||
assert len(mock_setup.mock_calls) == 0
|
||||
|
||||
# Verify an issue is raised that we were unable to import configuration
|
||||
issue = issue_registry.issues.get((DOMAIN, "deprecated_yaml"))
|
||||
assert issue
|
||||
assert issue.translation_key == "deprecated_yaml_import_issue_cannot_connect"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"status_code",
|
||||
[
|
||||
(HTTPStatus.UNAUTHORIZED),
|
||||
(HTTPStatus.INTERNAL_SERVER_ERROR),
|
||||
],
|
||||
)
|
||||
async def test_import_fitbit_config_cannot_refresh(
|
||||
hass: HomeAssistant,
|
||||
fitbit_config_setup: None,
|
||||
sensor_platform_setup: Callable[[], Awaitable[bool]],
|
||||
issue_registry: ir.IssueRegistry,
|
||||
requests_mock: Mocker,
|
||||
status_code: HTTPStatus,
|
||||
) -> None:
|
||||
"""Test platform configuration import fails when refreshing the token."""
|
||||
|
||||
requests_mock.register_uri(
|
||||
"POST",
|
||||
OAUTH2_TOKEN,
|
||||
status_code=status_code,
|
||||
json="",
|
||||
)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.fitbit.async_setup_entry", return_value=True
|
||||
) as mock_setup:
|
||||
await sensor_platform_setup()
|
||||
|
||||
assert len(mock_setup.mock_calls) == 0
|
||||
|
||||
# Verify an issue is raised that we were unable to import configuration
|
||||
issue = issue_registry.issues.get((DOMAIN, "deprecated_yaml"))
|
||||
assert issue
|
||||
assert issue.translation_key == "deprecated_yaml_import_issue_cannot_connect"
|
||||
|
||||
|
||||
async def test_import_fitbit_config_already_exists(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
setup_credentials: None,
|
||||
integration_setup: Callable[[], Awaitable[bool]],
|
||||
fitbit_config_setup: None,
|
||||
sensor_platform_setup: Callable[[], Awaitable[bool]],
|
||||
issue_registry: ir.IssueRegistry,
|
||||
requests_mock: Mocker,
|
||||
) -> None:
|
||||
"""Test that platform configuration is not imported if it already exists."""
|
||||
|
||||
requests_mock.register_uri(
|
||||
"POST",
|
||||
OAUTH2_TOKEN,
|
||||
status_code=HTTPStatus.OK,
|
||||
json=SERVER_ACCESS_TOKEN,
|
||||
)
|
||||
|
||||
# Verify existing config entry
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.fitbit.async_setup_entry", return_value=True
|
||||
) as mock_config_entry_setup:
|
||||
await integration_setup()
|
||||
|
||||
assert len(mock_config_entry_setup.mock_calls) == 1
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.fitbit.async_setup_entry", return_value=True
|
||||
) as mock_import_setup:
|
||||
await sensor_platform_setup()
|
||||
|
||||
assert len(mock_import_setup.mock_calls) == 0
|
||||
|
||||
# Still one config entry
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
|
||||
# Verify an issue is raised for deprecated configuration.yaml
|
||||
issue = issue_registry.issues.get((DOMAIN, "deprecated_yaml"))
|
||||
assert issue
|
||||
assert issue.translation_key == "deprecated_yaml_import"
|
||||
|
||||
|
||||
async def test_platform_setup_without_import(
|
||||
hass: HomeAssistant,
|
||||
sensor_platform_setup: Callable[[], Awaitable[bool]],
|
||||
issue_registry: ir.IssueRegistry,
|
||||
) -> None:
|
||||
"""Test platform configuration.yaml but no existing fitbit.conf credentials."""
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.fitbit.async_setup_entry", return_value=True
|
||||
) as mock_setup:
|
||||
await sensor_platform_setup()
|
||||
|
||||
# Verify no configuration entry is imported since the integration is not
|
||||
# fully setup properly
|
||||
assert len(mock_setup.mock_calls) == 0
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 0
|
||||
|
||||
# Verify an issue is raised for deprecated configuration.yaml
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = issue_registry.issues.get((DOMAIN, "deprecated_yaml"))
|
||||
assert issue
|
||||
assert issue.translation_key == "deprecated_yaml_no_import"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("current_request_with_host")
|
||||
async def test_reauth_flow(
|
||||
hass: HomeAssistant,
|
||||
|
|
|
@ -212,8 +212,8 @@ def mock_token_refresh(requests_mock: Mocker) -> None:
|
|||
)
|
||||
async def test_sensors(
|
||||
hass: HomeAssistant,
|
||||
fitbit_config_setup: None,
|
||||
sensor_platform_setup: Callable[[], Awaitable[bool]],
|
||||
setup_credentials: None,
|
||||
integration_setup: Callable[[], Awaitable[bool]],
|
||||
register_timeseries: Callable[[str, dict[str, Any]], None],
|
||||
entity_registry: er.EntityRegistry,
|
||||
entity_id: str,
|
||||
|
@ -226,7 +226,7 @@ async def test_sensors(
|
|||
register_timeseries(
|
||||
api_resource, timeseries_response(api_resource.replace("/", "-"), api_value)
|
||||
)
|
||||
await sensor_platform_setup()
|
||||
await integration_setup()
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
|
||||
|
@ -243,13 +243,13 @@ async def test_sensors(
|
|||
)
|
||||
async def test_device_battery(
|
||||
hass: HomeAssistant,
|
||||
fitbit_config_setup: None,
|
||||
sensor_platform_setup: Callable[[], Awaitable[bool]],
|
||||
setup_credentials: None,
|
||||
integration_setup: Callable[[], Awaitable[bool]],
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test battery level sensor for devices."""
|
||||
|
||||
assert await sensor_platform_setup()
|
||||
assert await integration_setup()
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
|
||||
|
@ -290,13 +290,13 @@ async def test_device_battery(
|
|||
)
|
||||
async def test_device_battery_level(
|
||||
hass: HomeAssistant,
|
||||
fitbit_config_setup: None,
|
||||
sensor_platform_setup: Callable[[], Awaitable[bool]],
|
||||
setup_credentials: None,
|
||||
integration_setup: Callable[[], Awaitable[bool]],
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test battery level sensor for devices."""
|
||||
|
||||
assert await sensor_platform_setup()
|
||||
assert await integration_setup()
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
|
||||
|
@ -347,15 +347,15 @@ async def test_device_battery_level(
|
|||
)
|
||||
async def test_profile_local(
|
||||
hass: HomeAssistant,
|
||||
fitbit_config_setup: None,
|
||||
sensor_platform_setup: Callable[[], Awaitable[bool]],
|
||||
setup_credentials: None,
|
||||
integration_setup: Callable[[], Awaitable[bool]],
|
||||
register_timeseries: Callable[[str, dict[str, Any]], None],
|
||||
expected_unit: str,
|
||||
) -> None:
|
||||
"""Test the fitbit profile locale impact on unit of measure."""
|
||||
|
||||
register_timeseries("body/weight", timeseries_response("body-weight", "175"))
|
||||
await sensor_platform_setup()
|
||||
await integration_setup()
|
||||
entries = hass.config_entries.async_entries(DOMAIN)
|
||||
assert len(entries) == 1
|
||||
|
||||
|
@ -365,7 +365,7 @@ async def test_profile_local(
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("sensor_platform_config", "api_response", "expected_state"),
|
||||
("imported_config_data", "api_response", "expected_state"),
|
||||
[
|
||||
(
|
||||
{"clock_format": "12H", "monitored_resources": ["sleep/startTime"]},
|
||||
|
@ -396,8 +396,8 @@ async def test_profile_local(
|
|||
)
|
||||
async def test_sleep_time_clock_format(
|
||||
hass: HomeAssistant,
|
||||
fitbit_config_setup: None,
|
||||
sensor_platform_setup: Callable[[], Awaitable[bool]],
|
||||
setup_credentials: None,
|
||||
integration_setup: Callable[[], Awaitable[bool]],
|
||||
register_timeseries: Callable[[str, dict[str, Any]], None],
|
||||
api_response: str,
|
||||
expected_state: str,
|
||||
|
@ -407,7 +407,7 @@ async def test_sleep_time_clock_format(
|
|||
register_timeseries(
|
||||
"sleep/startTime", timeseries_response("sleep-startTime", api_response)
|
||||
)
|
||||
await sensor_platform_setup()
|
||||
assert await integration_setup()
|
||||
|
||||
state = hass.states.get("sensor.sleep_start_time")
|
||||
assert state
|
||||
|
|
Loading…
Reference in New Issue