Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve BMW test quality #133704

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions tests/components/bmw_connected_drive/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@
"Error executing remote service on vehicle. HTTPStatusError: 502 Bad Gateway"
)

BIMMER_CONNECTED_LOGIN_PATCH = (
"homeassistant.components.bmw_connected_drive.config_flow.MyBMWAuthentication.login"
)
BIMMER_CONNECTED_VEHICLE_PATCH = (
"homeassistant.components.bmw_connected_drive.coordinator.MyBMWAccount.get_vehicles"
)


async def setup_mocked_integration(hass: HomeAssistant) -> MockConfigEntry:
"""Mock a fully setup config entry and all components based on fixtures."""
Expand Down
168 changes: 97 additions & 71 deletions tests/components/bmw_connected_drive/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
CONF_READ_ONLY,
CONF_REFRESH_TOKEN,
)
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.const import CONF_PASSWORD, CONF_REGION, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType

from . import (
BIMMER_CONNECTED_LOGIN_PATCH,
BIMMER_CONNECTED_VEHICLE_PATCH,
FIXTURE_CAPTCHA_INPUT,
FIXTURE_CONFIG_ENTRY,
FIXTURE_GCID,
Expand All @@ -40,40 +42,59 @@ def login_sideeffect(self: MyBMWAuthentication):
self.gcid = FIXTURE_GCID


async def test_show_form(hass: HomeAssistant) -> None:
"""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"] is FlowResultType.FORM
assert result["step_id"] == "user"


async def test_authentication_error(hass: HomeAssistant) -> None:
"""Test we show user form on MyBMW authentication error."""

with patch(
"bimmer_connected.api.authentication.MyBMWAuthentication.login",
side_effect=MyBMWAuthError("Login failed"),
async def test_full_user_flow_implementation(hass: HomeAssistant) -> None:
"""Test registering an integration and finishing flow works."""
with (
patch(
BIMMER_CONNECTED_LOGIN_PATCH,
side_effect=login_sideeffect,
autospec=True,
),
patch(
"homeassistant.components.bmw_connected_drive.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_USER},
data=deepcopy(FIXTURE_USER_INPUT_W_CAPTCHA),
data=deepcopy(FIXTURE_USER_INPUT),
)

assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] == {"base": "invalid_auth"}
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "captcha"

result = await hass.config_entries.flow.async_configure(
result["flow_id"], FIXTURE_CAPTCHA_INPUT
)

assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == FIXTURE_COMPLETE_ENTRY[CONF_USERNAME]
assert result["data"] == FIXTURE_COMPLETE_ENTRY
assert (
result["result"].unique_id
== f"{FIXTURE_USER_INPUT[CONF_REGION]}-{FIXTURE_USER_INPUT[CONF_USERNAME]}"
)

assert len(mock_setup_entry.mock_calls) == 1


async def test_connection_error(hass: HomeAssistant) -> None:
"""Test we show user form on MyBMW API error."""
@pytest.mark.parametrize(
("side_effect", "error"),
[
(MyBMWAuthError("Login failed"), "invalid_auth"),
(RequestError("Connection reset"), "cannot_connect"),
(MyBMWAPIError("400 Bad Request"), "cannot_connect"),
],
)
async def test_error_display_with_successful_login(
hass: HomeAssistant, side_effect: Exception, error: str
) -> None:
"""Test we show user form on MyBMW authentication error and are still able to succeed."""

with patch(
"bimmer_connected.api.authentication.MyBMWAuthentication.login",
side_effect=RequestError("Connection reset"),
BIMMER_CONNECTED_LOGIN_PATCH,
side_effect=side_effect,
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
Expand All @@ -83,25 +104,63 @@ async def test_connection_error(hass: HomeAssistant) -> None:

assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] == {"base": "cannot_connect"}
assert result["errors"] == {"base": error}

with (
patch(
BIMMER_CONNECTED_LOGIN_PATCH,
side_effect=login_sideeffect,
autospec=True,
),
patch(
"homeassistant.components.bmw_connected_drive.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
deepcopy(FIXTURE_USER_INPUT),
)

async def test_api_error(hass: HomeAssistant) -> None:
"""Test we show user form on general connection error."""
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "captcha"

with patch(
"bimmer_connected.api.authentication.MyBMWAuthentication.login",
side_effect=MyBMWAPIError("400 Bad Request"),
result = await hass.config_entries.flow.async_configure(
result["flow_id"], FIXTURE_CAPTCHA_INPUT
)

assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == FIXTURE_COMPLETE_ENTRY[CONF_USERNAME]
assert result["data"] == FIXTURE_COMPLETE_ENTRY
assert (
result["result"].unique_id
== f"{FIXTURE_USER_INPUT[CONF_REGION]}-{FIXTURE_USER_INPUT[CONF_USERNAME]}"
)

assert len(mock_setup_entry.mock_calls) == 1


async def test_unique_id_existing(hass: HomeAssistant) -> None:
"""Test registering an integration and when the unique id already exists."""

mock_config_entry = MockConfigEntry(**FIXTURE_CONFIG_ENTRY)
mock_config_entry.add_to_hass(hass)

with (
patch(
BIMMER_CONNECTED_LOGIN_PATCH,
side_effect=login_sideeffect,
autospec=True,
),
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_USER},
data=deepcopy(FIXTURE_USER_INPUT_W_CAPTCHA),
data=deepcopy(FIXTURE_USER_INPUT),
)

assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] == {"base": "cannot_connect"}
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"


@pytest.mark.usefixtures("bmw_fixture")
Expand All @@ -126,44 +185,11 @@ async def test_captcha_flow_missing_error(hass: HomeAssistant) -> None:
assert result["errors"] == {"base": "missing_captcha"}


async def test_full_user_flow_implementation(hass: HomeAssistant) -> None:
"""Test registering an integration and finishing flow works."""
with (
patch(
"bimmer_connected.api.authentication.MyBMWAuthentication.login",
side_effect=login_sideeffect,
autospec=True,
),
patch(
"homeassistant.components.bmw_connected_drive.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_USER},
data=deepcopy(FIXTURE_USER_INPUT),
)

assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "captcha"

result = await hass.config_entries.flow.async_configure(
result["flow_id"], FIXTURE_CAPTCHA_INPUT
)

assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == FIXTURE_COMPLETE_ENTRY[CONF_USERNAME]
assert result["data"] == FIXTURE_COMPLETE_ENTRY

assert len(mock_setup_entry.mock_calls) == 1


async def test_options_flow_implementation(hass: HomeAssistant) -> None:
"""Test config flow options."""
with (
patch(
"bimmer_connected.account.MyBMWAccount.get_vehicles",
BIMMER_CONNECTED_VEHICLE_PATCH,
return_value=[],
),
patch(
Expand Down Expand Up @@ -200,7 +226,7 @@ async def test_reauth(hass: HomeAssistant) -> None:
"""Test the reauth form."""
with (
patch(
"bimmer_connected.api.authentication.MyBMWAuthentication.login",
BIMMER_CONNECTED_LOGIN_PATCH,
side_effect=login_sideeffect,
autospec=True,
),
Expand Down Expand Up @@ -249,7 +275,7 @@ async def test_reauth(hass: HomeAssistant) -> None:
async def test_reconfigure(hass: HomeAssistant) -> None:
"""Test the reconfiguration form."""
with patch(
"bimmer_connected.api.authentication.MyBMWAuthentication.login",
BIMMER_CONNECTED_LOGIN_PATCH,
side_effect=login_sideeffect,
autospec=True,
):
Expand Down
Loading
Loading