Skip to content

Commit

Permalink
Ensure config_flow abort reasons have translations (home-assistant#12…
Browse files Browse the repository at this point in the history
…8140)

* Ensure config_flow abort reasons have translations

* Ignore fake_integration in application_credentials

* Mark gardena_bluetooth as needs fixing

* Mark google as needs fixing

* Mark google_assistant_sdk as needs fixing

* Mark homewizard as needs fixing

* Mark homeworks as needs fixing

* Mark honeywell as needs fixing

* Mark jewish_calendar as needs fixing

* Mark lg_netcast as needs fixing

* Mark lifx as needs fixing

* Mark lyric as needs fixing

* Mark madvr as needs fixing

* Mark matter as needs fixing

* Mark melcloud as needs fixing

* Mark motioneye as needs fixing

* Mark ollama as needs fixing

* Mark philips_js as needs fixing

* Mark spotify as needs fixing

* Mark srp_energy as needs fixing

* Mark subaru as needs fixing

* Mark tplink as needs fixing

* Mark yolink as needs fixing

* Mark youtube as needs fixing

* Fix incorrect comment
  • Loading branch information
epenet authored Oct 14, 2024
1 parent 821d9ab commit f41494b
Show file tree
Hide file tree
Showing 25 changed files with 215 additions and 3 deletions.
12 changes: 12 additions & 0 deletions tests/components/application_credentials/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@
TEST_DOMAIN = "fake_integration"


@pytest.fixture
def ignore_translations() -> list[str]:
"""Ignore specific translations.
We can ignore translations for the fake_integration we are testing with.
"""
return [
f"component.{TEST_DOMAIN}.config.abort.missing_configuration",
f"component.{TEST_DOMAIN}.config.abort.missing_credentials",
]


@pytest.fixture
async def authorization_server() -> AuthorizationServer:
"""Fixture AuthorizationServer for mock application_credentials integration."""
Expand Down
92 changes: 92 additions & 0 deletions tests/components/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,16 @@
from aiohasupervisor.models import Repository, StoreAddon, StoreInfo
import pytest

from homeassistant.config_entries import (
DISCOVERY_SOURCES,
SOURCE_SYSTEM,
ConfigEntriesFlowManager,
FlowResult,
)
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowHandler, FlowManager, FlowResultType
from homeassistant.helpers.translation import async_get_translations

if TYPE_CHECKING:
from homeassistant.components.hassio import AddonManager
Expand Down Expand Up @@ -456,3 +464,87 @@ def supervisor_client() -> Generator[AsyncMock]:
),
):
yield supervisor_client


async def _ensure_translation_exists(
hass: HomeAssistant,
ignore_translations: list[str],
category: str,
component: str,
key: str,
) -> None:
"""Raise if translation doesn't exist."""
full_key = f"component.{component}.{category}.{key}"
if full_key in ignore_translations:
return

translations = await async_get_translations(hass, "en", category, [component])
if full_key in translations:
return

key_parts = key.split(".")
# Ignore step data translations if title or description exists
if (
len(key_parts) >= 3
and key_parts[0] == "step"
and key_parts[2] == "data"
and (
f"component.{component}.{category}.{key_parts[0]}.{key_parts[1]}.description"
in translations
or f"component.{component}.{category}.{key_parts[0]}.{key_parts[1]}.title"
in translations
)
):
return

raise ValueError(
f"Translation not found for {component}: `{category}.{key}`. "
f"Please add to homeassistant/components/{component}/strings.json"
)


@pytest.fixture
def ignore_translations() -> list[str]:
"""Ignore specific translations.
Override or parametrize this fixture with a fixture that returns,
a list of translation that should be ignored.
"""
return []


@pytest.fixture(autouse=True)
def check_config_translations(ignore_translations: list[str]) -> Generator[None]:
"""Ensure config_flow translations are available."""
_original = FlowManager._async_handle_step

async def _async_handle_step(
self: FlowManager, flow: FlowHandler, *args
) -> FlowResult:
result = await _original(self, flow, *args)
if isinstance(self, ConfigEntriesFlowManager):
category = "config"
component = flow.handler
else:
return result

if (
result["type"] is FlowResultType.ABORT
and flow.source != SOURCE_SYSTEM
and flow.source not in DISCOVERY_SOURCES
):
await _ensure_translation_exists(
flow.hass,
ignore_translations,
category,
component,
f"abort.{result["reason"]}",
)

return result

with patch(
"homeassistant.data_entry_flow.FlowManager._async_handle_step",
_async_handle_step,
):
yield
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
'version': 1,
})
# ---
# name: test_failed_connect
# name: test_failed_connect[component.gardena_bluetooth.config.abort.cannot_connect]
FlowResultSnapshot({
'data_schema': list([
dict({
Expand All @@ -163,7 +163,7 @@
'type': <FlowResultType.FORM: 'form'>,
})
# ---
# name: test_failed_connect.1
# name: test_failed_connect[component.gardena_bluetooth.config.abort.cannot_connect].1
FlowResultSnapshot({
'data_schema': None,
'description_placeholders': dict({
Expand All @@ -178,7 +178,7 @@
'type': <FlowResultType.FORM: 'form'>,
})
# ---
# name: test_failed_connect.2
# name: test_failed_connect[component.gardena_bluetooth.config.abort.cannot_connect].2
FlowResultSnapshot({
'description_placeholders': dict({
'error': 'something went wrong',
Expand Down
4 changes: 4 additions & 0 deletions tests/components/gardena_bluetooth/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ async def test_user_selection(
assert result == snapshot


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.gardena_bluetooth.config.abort.cannot_connect"],
)
async def test_failed_connect(
hass: HomeAssistant,
mock_client: Mock,
Expand Down
4 changes: 4 additions & 0 deletions tests/components/google/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ async def test_multiple_config_entries(
assert len(entries) == 2


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.google.config.abort.missing_credentials"],
)
async def test_missing_configuration(
hass: HomeAssistant,
) -> None:
Expand Down
4 changes: 4 additions & 0 deletions tests/components/google_assistant_sdk/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ async def test_reauth(
assert config_entry.data["token"].get("refresh_token") == "mock-refresh-token"


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.google_assistant_sdk.config.abort.single_instance_allowed"],
)
@pytest.mark.usefixtures("current_request_with_host")
async def test_single_instance_allowed(
hass: HomeAssistant,
Expand Down
4 changes: 4 additions & 0 deletions tests/components/homewizard/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ async def test_error_flow(
assert result["type"] is FlowResultType.CREATE_ENTRY


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.homewizard.config.abort.unsupported_api_version"],
)
@pytest.mark.parametrize(
("exception", "reason"),
[
Expand Down
8 changes: 8 additions & 0 deletions tests/components/homeworks/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ async def test_user_flow_cannot_connect(
assert result["step_id"] == "user"


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.homeworks.config.abort.reconfigure_successful"],
)
async def test_reconfigure_flow(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_homeworks: MagicMock
) -> None:
Expand Down Expand Up @@ -322,6 +326,10 @@ async def test_reconfigure_flow_flow_duplicate(
assert result["errors"] == {"base": "duplicated_host_port"}


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.homeworks.config.abort.reconfigure_successful"],
)
async def test_reconfigure_flow_flow_no_change(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_homeworks: MagicMock
) -> None:
Expand Down
4 changes: 4 additions & 0 deletions tests/components/honeywell/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ async def test_create_option_entry(
}


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.honeywell.config.abort.reauth_successful"],
)
async def test_reauth_flow(hass: HomeAssistant) -> None:
"""Test a successful reauth flow."""

Expand Down
4 changes: 4 additions & 0 deletions tests/components/jewish_calendar/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ async def test_options_reconfigure(
)


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.jewish_calendar.config.abort.reconfigure_successful"],
)
async def test_reconfigure(
hass: HomeAssistant, mock_config_entry: MockConfigEntry
) -> None:
Expand Down
6 changes: 6 additions & 0 deletions tests/components/lg_netcast/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from datetime import timedelta
from unittest.mock import DEFAULT, patch

import pytest

from homeassistant import data_entry_flow
from homeassistant.components.lg_netcast.const import DOMAIN
from homeassistant.config_entries import SOURCE_USER
Expand Down Expand Up @@ -112,6 +114,10 @@ async def test_manual_host_unsuccessful_details_response(hass: HomeAssistant) ->
assert result["reason"] == "cannot_connect"


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.lg_netcast.config.abort.invalid_host"],
)
async def test_manual_host_no_unique_id_response(hass: HomeAssistant) -> None:
"""Test manual host configuration."""
with _patch_lg_netcast(no_unique_id=True):
Expand Down
4 changes: 4 additions & 0 deletions tests/components/lifx/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ async def test_discovery(hass: HomeAssistant) -> None:
assert result2["reason"] == "no_devices_found"


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.lifx.config.abort.cannot_connect"],
)
async def test_discovery_but_cannot_connect(hass: HomeAssistant) -> None:
"""Test we can discover the device but we cannot connect."""
with _patch_discovery(), _patch_config_flow_try_connect(no_device=True):
Expand Down
4 changes: 4 additions & 0 deletions tests/components/lyric/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ async def mock_impl(hass: HomeAssistant) -> None:
)


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.lyric.config.abort.missing_credentials"],
)
async def test_abort_if_no_configuration(hass: HomeAssistant) -> None:
"""Check flow abort when no configuration."""
result = await hass.config_entries.flow.async_init(
Expand Down
4 changes: 4 additions & 0 deletions tests/components/madvr/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ async def test_reconfigure_flow(
mock_madvr_client.async_cancel_tasks.assert_called()


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.madvr.config.abort.set_up_new_device"],
)
async def test_reconfigure_new_device(
hass: HomeAssistant,
mock_madvr_client: AsyncMock,
Expand Down
4 changes: 4 additions & 0 deletions tests/components/matter/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,10 @@ async def test_addon_running(
assert setup_entry.call_count == 1


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.matter.config.abort.cannot_connect"],
)
@pytest.mark.parametrize(
(
"discovery_info",
Expand Down
13 changes: 13 additions & 0 deletions tests/components/melcloud/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ async def test_form(hass: HomeAssistant, mock_login, mock_get_devices) -> None:
assert len(mock_setup_entry.mock_calls) == 1


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.melcloud.config.abort.cannot_connect"],
)
@pytest.mark.parametrize(
("error", "reason"),
[(ClientError(), "cannot_connect"), (TimeoutError(), "cannot_connect")],
Expand All @@ -94,6 +98,15 @@ async def test_form_errors(
assert result["reason"] == reason


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
[
[
"component.melcloud.config.abort.cannot_connect",
"component.melcloud.config.abort.invalid_auth",
],
],
)
@pytest.mark.parametrize(
("error", "message"),
[
Expand Down
5 changes: 5 additions & 0 deletions tests/components/motioneye/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
MotionEyeClientInvalidAuthError,
MotionEyeClientRequestError,
)
import pytest

from homeassistant import config_entries
from homeassistant.components.hassio import HassioServiceInfo
Expand Down Expand Up @@ -390,6 +391,10 @@ async def test_hassio_ignored(hass: HomeAssistant) -> None:
assert result.get("reason") == "already_configured"


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.motioneye.config.abort.already_in_progress"],
)
async def test_hassio_abort_if_already_in_progress(hass: HomeAssistant) -> None:
"""Test Supervisor discovered flow aborts if user flow in progress."""
result = await hass.config_entries.flow.async_init(
Expand Down
4 changes: 4 additions & 0 deletions tests/components/ollama/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ async def test_form_errors(hass: HomeAssistant, side_effect, error) -> None:
assert result2["errors"] == {"base": error}


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.ollama.config.abort.download_failed"],
)
async def test_download_error(hass: HomeAssistant) -> None:
"""Test we handle errors while downloading a model."""
result = await hass.config_entries.flow.async_init(
Expand Down
8 changes: 8 additions & 0 deletions tests/components/philips_js/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ async def test_pairing(hass: HomeAssistant, mock_tv_pairable, mock_setup_entry)
assert len(mock_setup_entry.mock_calls) == 1


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.philips_js.config.abort.pairing_failure"],
)
async def test_pair_request_failed(
hass: HomeAssistant, mock_tv_pairable, mock_setup_entry
) -> None:
Expand Down Expand Up @@ -188,6 +192,10 @@ async def test_pair_request_failed(
}


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.philips_js.config.abort.pairing_failure"],
)
async def test_pair_grant_failed(
hass: HomeAssistant, mock_tv_pairable, mock_setup_entry
) -> None:
Expand Down
4 changes: 4 additions & 0 deletions tests/components/spotify/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
)


@pytest.mark.parametrize( # Remove when translations fixed
"ignore_translations",
["component.spotify.config.abort.missing_credentials"],
)
async def test_abort_if_no_configuration(hass: HomeAssistant) -> None:
"""Check flow aborts when no configuration is present."""
result = await hass.config_entries.flow.async_init(
Expand Down
Loading

0 comments on commit f41494b

Please sign in to comment.