Replace garminconnect_aio with garminconnect_ha (#51730)

* Fixed config_flow for multiple account creation

* Replaced python package to fix multiple accounts

* Replaced python package to fix multiple accounts

* Implemented config entries user

* Config entries user

* Fixed test code config flow

* Fixed patch
This commit is contained in:
Ron Klinkien 2021-06-12 10:05:27 +02:00 committed by GitHub
parent 30c53a1a13
commit f6e0165543
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 69 deletions

View file

@ -2,7 +2,7 @@
from datetime import date
import logging
from garminconnect_aio import (
from garminconnect_ha import (
Garmin,
GarminConnectAuthenticationError,
GarminConnectConnectionError,
@ -13,7 +13,6 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.util import Throttle
from .const import DEFAULT_UPDATE_INTERVAL, DOMAIN
@ -26,14 +25,13 @@ PLATFORMS = ["sensor"]
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Garmin Connect from a config entry."""
websession = async_get_clientsession(hass)
username: str = entry.data[CONF_USERNAME]
password: str = entry.data[CONF_PASSWORD]
garmin_client = Garmin(websession, username, password)
api = Garmin(username, password)
try:
await garmin_client.login()
await hass.async_add_executor_job(api.login)
except (
GarminConnectAuthenticationError,
GarminConnectTooManyRequestsError,
@ -49,7 +47,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
_LOGGER.exception("Unknown error occurred during Garmin Connect login request")
return False
garmin_data = GarminConnectData(hass, garmin_client)
garmin_data = GarminConnectData(hass, api)
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = garmin_data
@ -81,14 +79,20 @@ class GarminConnectData:
today = date.today()
try:
summary = await self.client.get_user_summary(today.isoformat())
body = await self.client.get_body_composition(today.isoformat())
summary = await self.hass.async_add_executor_job(
self.client.get_user_summary, today.isoformat()
)
body = await self.hass.async_add_executor_job(
self.client.get_body_composition, today.isoformat()
)
self.data = {
**summary,
**body["totalAverage"],
}
self.data["nextAlarm"] = await self.client.get_device_alarms()
self.data["nextAlarm"] = await self.hass.async_add_executor_job(
self.client.get_device_alarms
)
except (
GarminConnectAuthenticationError,
GarminConnectTooManyRequestsError,

View file

@ -1,7 +1,7 @@
"""Config flow for Garmin Connect integration."""
import logging
from garminconnect_aio import (
from garminconnect_ha import (
Garmin,
GarminConnectAuthenticationError,
GarminConnectConnectionError,
@ -11,7 +11,6 @@ import voluptuous as vol
from homeassistant import config_entries
from homeassistant.const import CONF_ID, CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN
@ -38,15 +37,14 @@ class GarminConnectConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if user_input is None:
return await self._show_setup_form()
websession = async_get_clientsession(self.hass)
username = user_input[CONF_USERNAME]
password = user_input[CONF_PASSWORD]
garmin_client = Garmin(websession, username, password)
api = Garmin(username, password)
errors = {}
try:
await garmin_client.login()
await self.hass.async_add_executor_job(api.login)
except GarminConnectConnectionError:
errors["base"] = "cannot_connect"
return await self._show_setup_form(errors)

View file

@ -2,8 +2,8 @@
"domain": "garmin_connect",
"name": "Garmin Connect",
"documentation": "https://www.home-assistant.io/integrations/garmin_connect",
"requirements": ["garminconnect_aio==0.1.4"],
"requirements": ["garminconnect_ha==0.1.6"],
"codeowners": ["@cyberjunky"],
"config_flow": true,
"iot_class": "cloud_polling"
}
}

View file

@ -641,7 +641,7 @@ gTTS==2.2.2
garages-amsterdam==2.1.1
# homeassistant.components.garmin_connect
garminconnect_aio==0.1.4
garminconnect_ha==0.1.6
# homeassistant.components.geniushub
geniushub-client==0.6.30

View file

@ -347,7 +347,7 @@ gTTS==2.2.2
garages-amsterdam==2.1.1
# homeassistant.components.garmin_connect
garminconnect_aio==0.1.4
garminconnect_ha==0.1.6
# homeassistant.components.geo_json_events
# homeassistant.components.usgs_earthquakes_feed

View file

@ -1,12 +1,11 @@
"""Test the Garmin Connect config flow."""
from unittest.mock import patch
from garminconnect_aio import (
from garminconnect_ha import (
GarminConnectAuthenticationError,
GarminConnectConnectionError,
GarminConnectTooManyRequestsError,
)
import pytest
from homeassistant import config_entries, data_entry_flow
from homeassistant.components.garmin_connect.const import DOMAIN
@ -21,37 +20,23 @@ MOCK_CONF = {
}
@pytest.fixture(name="mock_garmin_connect")
def mock_garmin():
"""Mock Garmin Connect."""
with patch(
"homeassistant.components.garmin_connect.config_flow.Garmin",
) as garmin:
garmin.return_value.login.return_value = MOCK_CONF[CONF_ID]
yield garmin.return_value
async def test_show_form(hass):
"""Test that the form is served with no input."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["errors"] == {}
assert result["step_id"] == config_entries.SOURCE_USER
async def test_step_user(hass):
"""Test registering an integration and finishing flow works."""
with patch(
"homeassistant.components.garmin_connect.Garmin.login",
return_value="my@email.address",
), patch(
"homeassistant.components.garmin_connect.async_setup_entry", return_value=True
):
), patch(
"homeassistant.components.garmin_connect.config_flow.Garmin",
) as garmin:
garmin.return_value.login.return_value = MOCK_CONF[CONF_ID]
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_CONF
)
@ -59,60 +44,69 @@ async def test_step_user(hass):
assert result["data"] == MOCK_CONF
async def test_connection_error(hass, mock_garmin_connect):
async def test_connection_error(hass):
"""Test for connection error."""
mock_garmin_connect.login.side_effect = GarminConnectConnectionError("errormsg")
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_CONF
)
with patch(
"homeassistant.components.garmin_connect.Garmin.login",
side_effect=GarminConnectConnectionError("errormsg"),
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "user"}, data=MOCK_CONF
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["errors"] == {"base": "cannot_connect"}
async def test_authentication_error(hass, mock_garmin_connect):
async def test_authentication_error(hass):
"""Test for authentication error."""
mock_garmin_connect.login.side_effect = GarminConnectAuthenticationError("errormsg")
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_CONF
)
with patch(
"homeassistant.components.garmin_connect.Garmin.login",
side_effect=GarminConnectAuthenticationError("errormsg"),
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "user"}, data=MOCK_CONF
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["errors"] == {"base": "invalid_auth"}
async def test_toomanyrequest_error(hass, mock_garmin_connect):
async def test_toomanyrequest_error(hass):
"""Test for toomanyrequests error."""
mock_garmin_connect.login.side_effect = GarminConnectTooManyRequestsError(
"errormsg"
)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_CONF
)
with patch(
"homeassistant.components.garmin_connect.Garmin.login",
side_effect=GarminConnectTooManyRequestsError("errormsg"),
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "user"}, data=MOCK_CONF
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["errors"] == {"base": "too_many_requests"}
async def test_unknown_error(hass, mock_garmin_connect):
async def test_unknown_error(hass):
"""Test for unknown error."""
mock_garmin_connect.login.side_effect = Exception
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}, data=MOCK_CONF
)
with patch(
"homeassistant.components.garmin_connect.Garmin.login",
side_effect=Exception,
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "user"}, data=MOCK_CONF
)
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["errors"] == {"base": "unknown"}
async def test_abort_if_already_setup(hass):
"""Test abort if already setup."""
MockConfigEntry(
domain=DOMAIN, data=MOCK_CONF, unique_id=MOCK_CONF[CONF_ID]
).add_to_hass(hass)
with patch(
"homeassistant.components.garmin_connect.config_flow.Garmin", autospec=True
) as garmin:
garmin.return_value.login.return_value = MOCK_CONF[CONF_ID]
"homeassistant.components.garmin_connect.config_flow.Garmin",
):
entry = MockConfigEntry(
domain=DOMAIN, data=MOCK_CONF, unique_id=MOCK_CONF[CONF_ID]
)
entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "user"}, data=MOCK_CONF
)
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"