Skip to content

Commit

Permalink
Replace garminconnect_aio with garminconnect_ha (#51730)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
cyberjunky authored and frenck committed Jun 15, 2021
1 parent 97e36cd commit fcc6613
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 69 deletions.
22 changes: 13 additions & 9 deletions homeassistant/components/garmin_connect/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 2,7 @@
from datetime import date
import logging

from garminconnect_aio import (
from garminconnect_ha import (
Garmin,
GarminConnectAuthenticationError,
GarminConnectConnectionError,
Expand All @@ -13,7 13,6 @@
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
Expand All @@ -26,14 25,13 @@
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"""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,
Expand All @@ -49,7 47,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
_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

Expand Down Expand Up @@ -81,14 79,20 @@ async def async_update(self):
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,
Expand Down
8 changes: 3 additions & 5 deletions homeassistant/components/garmin_connect/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,7 1,7 @@
"""Config flow for Garmin Connect integration."""
import logging

from garminconnect_aio import (
from garminconnect_ha import (
Garmin,
GarminConnectAuthenticationError,
GarminConnectConnectionError,
Expand All @@ -11,7 11,6 @@

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

Expand All @@ -38,15 37,14 @@ async def async_step_user(self, user_input=None):
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)
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/garmin_connect/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 635,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
Expand Down
2 changes: 1 addition & 1 deletion requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 341,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
Expand Down
96 changes: 45 additions & 51 deletions tests/components/garmin_connect/test_config_flow.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -21,98 20,93 @@
}


@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="[email protected]",
), 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
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
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"

0 comments on commit fcc6613

Please sign in to comment.