Simplify vizio unique ID check since only IP and device class are needed (#37692)
parent
444df4a7d2
commit
fbf44b37a9
|
@ -180,14 +180,8 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
self._data = None
|
self._data = None
|
||||||
self._apps = {}
|
self._apps = {}
|
||||||
|
|
||||||
async def _create_entry_if_unique(
|
async def _create_entry(self, input_dict: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
self, input_dict: Dict[str, Any]
|
"""Create vizio config entry."""
|
||||||
) -> Dict[str, Any]:
|
|
||||||
"""
|
|
||||||
Create entry if ID is unique.
|
|
||||||
|
|
||||||
If it is, create entry. If it isn't, abort config flow.
|
|
||||||
"""
|
|
||||||
# Remove extra keys that will not be used by entry setup
|
# Remove extra keys that will not be used by entry setup
|
||||||
input_dict.pop(CONF_APPS_TO_INCLUDE_OR_EXCLUDE, None)
|
input_dict.pop(CONF_APPS_TO_INCLUDE_OR_EXCLUDE, None)
|
||||||
input_dict.pop(CONF_INCLUDE_OR_EXCLUDE, None)
|
input_dict.pop(CONF_INCLUDE_OR_EXCLUDE, None)
|
||||||
|
@ -206,19 +200,25 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
# Store current values in case setup fails and user needs to edit
|
# Store current values in case setup fails and user needs to edit
|
||||||
self._user_schema = _get_config_schema(user_input)
|
self._user_schema = _get_config_schema(user_input)
|
||||||
|
unique_id = await VizioAsync.get_unique_id(
|
||||||
|
user_input[CONF_HOST],
|
||||||
|
user_input[CONF_DEVICE_CLASS],
|
||||||
|
session=async_get_clientsession(self.hass, False),
|
||||||
|
)
|
||||||
|
|
||||||
# Check if new config entry matches any existing config entries
|
if not unique_id:
|
||||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
errors[CONF_HOST] = "cannot_connect"
|
||||||
# If source is ignore bypass host and name check and continue through loop
|
else:
|
||||||
if entry.source == SOURCE_IGNORE:
|
# Set unique ID and abort if a flow with the same unique ID is already in progress
|
||||||
continue
|
existing_entry = await self.async_set_unique_id(
|
||||||
if await self.hass.async_add_executor_job(
|
unique_id=unique_id, raise_on_progress=True
|
||||||
_host_is_same, entry.data[CONF_HOST], user_input[CONF_HOST]
|
)
|
||||||
):
|
# If device was discovered, abort if existing entry found, otherwise display an error
|
||||||
errors[CONF_HOST] = "host_exists"
|
# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
|
||||||
|
if self.context["source"] == SOURCE_ZEROCONF:
|
||||||
if entry.data[CONF_NAME] == user_input[CONF_NAME]:
|
self._abort_if_unique_id_configured()
|
||||||
errors[CONF_NAME] = "name_exists"
|
elif existing_entry:
|
||||||
|
errors[CONF_HOST] = "existing_config_entry_found"
|
||||||
|
|
||||||
if not errors:
|
if not errors:
|
||||||
# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
|
# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
|
||||||
|
@ -239,21 +239,7 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
errors["base"] = "cannot_connect"
|
errors["base"] = "cannot_connect"
|
||||||
|
|
||||||
if not errors:
|
if not errors:
|
||||||
unique_id = await VizioAsync.get_unique_id(
|
return await self._create_entry(user_input)
|
||||||
user_input[CONF_HOST],
|
|
||||||
user_input.get(CONF_ACCESS_TOKEN),
|
|
||||||
user_input[CONF_DEVICE_CLASS],
|
|
||||||
session=async_get_clientsession(self.hass, False),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set unique ID and abort if unique ID is already configured on an entry or a flow
|
|
||||||
# with the unique ID is already in progress
|
|
||||||
await self.async_set_unique_id(
|
|
||||||
unique_id=unique_id, raise_on_progress=True
|
|
||||||
)
|
|
||||||
self._abort_if_unique_id_configured()
|
|
||||||
|
|
||||||
return await self._create_entry_if_unique(user_input)
|
|
||||||
# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
|
# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
|
||||||
elif self._must_show_form and self.context["source"] == SOURCE_IMPORT:
|
elif self._must_show_form and self.context["source"] == SOURCE_IMPORT:
|
||||||
# Import should always display the config form if CONF_ACCESS_TOKEN
|
# Import should always display the config form if CONF_ACCESS_TOKEN
|
||||||
|
@ -350,27 +336,10 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""Handle zeroconf discovery."""
|
"""Handle zeroconf discovery."""
|
||||||
|
|
||||||
# Set unique ID early to prevent device from getting rediscovered multiple times
|
|
||||||
await self.async_set_unique_id(
|
|
||||||
unique_id=discovery_info[CONF_HOST].split(":")[0], raise_on_progress=True
|
|
||||||
)
|
|
||||||
self._abort_if_unique_id_configured()
|
|
||||||
|
|
||||||
discovery_info[
|
discovery_info[
|
||||||
CONF_HOST
|
CONF_HOST
|
||||||
] = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}"
|
] = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}"
|
||||||
|
|
||||||
# Check if new config entry matches any existing config entries and abort if so
|
|
||||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
|
||||||
# If source is ignore bypass host check and continue through loop
|
|
||||||
if entry.source == SOURCE_IGNORE:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if await self.hass.async_add_executor_job(
|
|
||||||
_host_is_same, entry.data[CONF_HOST], discovery_info[CONF_HOST]
|
|
||||||
):
|
|
||||||
return self.async_abort(reason="already_configured_device")
|
|
||||||
|
|
||||||
# Set default name to discovered device name by stripping zeroconf service
|
# Set default name to discovered device name by stripping zeroconf service
|
||||||
# (`type`) from `name`
|
# (`type`) from `name`
|
||||||
num_chars_to_strip = len(discovery_info[CONF_TYPE]) + 1
|
num_chars_to_strip = len(discovery_info[CONF_TYPE]) + 1
|
||||||
|
@ -436,20 +405,6 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
self._data[CONF_ACCESS_TOKEN] = pair_data.auth_token
|
self._data[CONF_ACCESS_TOKEN] = pair_data.auth_token
|
||||||
self._must_show_form = True
|
self._must_show_form = True
|
||||||
|
|
||||||
unique_id = await VizioAsync.get_unique_id(
|
|
||||||
self._data[CONF_HOST],
|
|
||||||
self._data[CONF_ACCESS_TOKEN],
|
|
||||||
self._data[CONF_DEVICE_CLASS],
|
|
||||||
session=async_get_clientsession(self.hass, False),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set unique ID and abort if unique ID is already configured on an entry or a flow
|
|
||||||
# with the unique ID is already in progress
|
|
||||||
await self.async_set_unique_id(
|
|
||||||
unique_id=unique_id, raise_on_progress=True
|
|
||||||
)
|
|
||||||
self._abort_if_unique_id_configured()
|
|
||||||
|
|
||||||
# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
|
# pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167
|
||||||
if self.context["source"] == SOURCE_IMPORT:
|
if self.context["source"] == SOURCE_IMPORT:
|
||||||
# If user is pairing via config import, show different message
|
# If user is pairing via config import, show different message
|
||||||
|
@ -470,7 +425,7 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
async def _pairing_complete(self, step_id: str) -> Dict[str, Any]:
|
async def _pairing_complete(self, step_id: str) -> Dict[str, Any]:
|
||||||
"""Handle config flow completion."""
|
"""Handle config flow completion."""
|
||||||
if not self._must_show_form:
|
if not self._must_show_form:
|
||||||
return await self._create_entry_if_unique(self._data)
|
return await self._create_entry(self._data)
|
||||||
|
|
||||||
self._must_show_form = False
|
self._must_show_form = False
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"domain": "vizio",
|
"domain": "vizio",
|
||||||
"name": "VIZIO SmartCast",
|
"name": "VIZIO SmartCast",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/vizio",
|
"documentation": "https://www.home-assistant.io/integrations/vizio",
|
||||||
"requirements": ["pyvizio==0.1.49"],
|
"requirements": ["pyvizio==0.1.51"],
|
||||||
"codeowners": ["@raman325"],
|
"codeowners": ["@raman325"],
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"zeroconf": ["_viziocast._tcp.local."],
|
"zeroconf": ["_viziocast._tcp.local."],
|
||||||
|
|
|
@ -294,7 +294,7 @@ class VizioDevice(MediaPlayerEntity):
|
||||||
setting_type, setting_name, new_value,
|
setting_type, setting_name, new_value,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Register callbacks when entity is added."""
|
"""Register callbacks when entity is added."""
|
||||||
# Register callback for when config entry is updated.
|
# Register callback for when config entry is updated.
|
||||||
self._async_unsub_listeners.append(
|
self._async_unsub_listeners.append(
|
||||||
|
@ -310,7 +310,7 @@ class VizioDevice(MediaPlayerEntity):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Disconnect callbacks when entity is removed."""
|
"""Disconnect callbacks when entity is removed."""
|
||||||
for listener in self._async_unsub_listeners:
|
for listener in self._async_unsub_listeners:
|
||||||
listener()
|
listener()
|
||||||
|
@ -323,7 +323,7 @@ class VizioDevice(MediaPlayerEntity):
|
||||||
return self._available
|
return self._available
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self) -> str:
|
def state(self) -> Optional[str]:
|
||||||
"""Return the state of the device."""
|
"""Return the state of the device."""
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ class VizioDevice(MediaPlayerEntity):
|
||||||
return self._icon
|
return self._icon
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def volume_level(self) -> float:
|
def volume_level(self) -> Optional[float]:
|
||||||
"""Return the volume level of the device."""
|
"""Return the volume level of the device."""
|
||||||
return self._volume_level
|
return self._volume_level
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ class VizioDevice(MediaPlayerEntity):
|
||||||
return self._is_volume_muted
|
return self._is_volume_muted
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def source(self) -> str:
|
def source(self) -> Optional[str]:
|
||||||
"""Return current input of the device."""
|
"""Return current input of the device."""
|
||||||
if self._current_app is not None and self._current_input in INPUT_APPS:
|
if self._current_app is not None and self._current_input in INPUT_APPS:
|
||||||
return self._current_app
|
return self._current_app
|
||||||
|
|
|
@ -28,10 +28,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"host_exists": "[%key:component::vizio::config::step::user::title%] with specified host already configured.",
|
|
||||||
"name_exists": "[%key:component::vizio::config::step::user::title%] with specified name already configured.",
|
|
||||||
"complete_pairing_failed": "Unable to complete pairing. Ensure the PIN you provided is correct and the TV is still powered and connected to the network before resubmitting.",
|
"complete_pairing_failed": "Unable to complete pairing. Ensure the PIN you provided is correct and the TV is still powered and connected to the network before resubmitting.",
|
||||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||||
|
"existing_config_entry_found": "An existing [%key:component::vizio::config::step::user::title%] config entry with the same serial number has already been configured. You must delete the existing entry in order to configure this one."
|
||||||
},
|
},
|
||||||
"abort": {
|
"abort": {
|
||||||
"already_configured_device": "[%key:common::config_flow::abort::already_configured_device%]",
|
"already_configured_device": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||||
|
|
|
@ -1834,7 +1834,7 @@ pyversasense==0.0.6
|
||||||
pyvesync==1.1.0
|
pyvesync==1.1.0
|
||||||
|
|
||||||
# homeassistant.components.vizio
|
# homeassistant.components.vizio
|
||||||
pyvizio==0.1.49
|
pyvizio==0.1.51
|
||||||
|
|
||||||
# homeassistant.components.velux
|
# homeassistant.components.velux
|
||||||
pyvlx==0.2.16
|
pyvlx==0.2.16
|
||||||
|
|
|
@ -839,7 +839,7 @@ pyvera==0.3.9
|
||||||
pyvesync==1.1.0
|
pyvesync==1.1.0
|
||||||
|
|
||||||
# homeassistant.components.vizio
|
# homeassistant.components.vizio
|
||||||
pyvizio==0.1.49
|
pyvizio==0.1.51
|
||||||
|
|
||||||
# homeassistant.components.volumio
|
# homeassistant.components.volumio
|
||||||
pyvolumio==0.1.1
|
pyvolumio==0.1.1
|
||||||
|
|
|
@ -47,15 +47,32 @@ def skip_notifications_fixture():
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="vizio_get_unique_id", autouse=True)
|
||||||
|
def vizio_get_unique_id_fixture():
|
||||||
|
"""Mock get vizio unique ID."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.vizio.config_flow.VizioAsync.get_unique_id",
|
||||||
|
return_value=UNIQUE_ID,
|
||||||
|
):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="vizio_no_unique_id")
|
||||||
|
def vizio_no_unique_id_fixture():
|
||||||
|
"""Mock no vizio unique ID returrned."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.vizio.config_flow.VizioAsync.get_unique_id",
|
||||||
|
return_value=None,
|
||||||
|
):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="vizio_connect")
|
@pytest.fixture(name="vizio_connect")
|
||||||
def vizio_connect_fixture():
|
def vizio_connect_fixture():
|
||||||
"""Mock valid vizio device and entry setup."""
|
"""Mock valid vizio device and entry setup."""
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.vizio.config_flow.VizioAsync.validate_ha_config",
|
"homeassistant.components.vizio.config_flow.VizioAsync.validate_ha_config",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
), patch(
|
|
||||||
"homeassistant.components.vizio.config_flow.VizioAsync.get_unique_id",
|
|
||||||
return_value=UNIQUE_ID,
|
|
||||||
):
|
):
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ from .const import (
|
||||||
NAME2,
|
NAME2,
|
||||||
UNIQUE_ID,
|
UNIQUE_ID,
|
||||||
VOLUME_STEP,
|
VOLUME_STEP,
|
||||||
ZEROCONF_HOST,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
@ -223,7 +222,10 @@ async def test_user_host_already_configured(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test host is already configured during user setup."""
|
"""Test host is already configured during user setup."""
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=DOMAIN, data=MOCK_SPEAKER_CONFIG, options={CONF_VOLUME_STEP: VOLUME_STEP}
|
domain=DOMAIN,
|
||||||
|
data=MOCK_SPEAKER_CONFIG,
|
||||||
|
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||||
|
unique_id=UNIQUE_ID,
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
fail_entry = MOCK_SPEAKER_CONFIG.copy()
|
fail_entry = MOCK_SPEAKER_CONFIG.copy()
|
||||||
|
@ -234,61 +236,15 @@ async def test_user_host_already_configured(
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["errors"] == {CONF_HOST: "host_exists"}
|
assert result["errors"] == {CONF_HOST: "existing_config_entry_found"}
|
||||||
|
|
||||||
|
|
||||||
async def test_user_host_already_configured_no_port(
|
async def test_user_serial_number_already_exists(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
vizio_connect: pytest.fixture,
|
vizio_connect: pytest.fixture,
|
||||||
vizio_bypass_setup: pytest.fixture,
|
vizio_bypass_setup: pytest.fixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test host is already configured during user setup when existing entry has no port."""
|
"""Test serial_number is already configured with different host and name during user setup."""
|
||||||
# Mock entry without port so we can test that the same entry WITH a port will fail
|
|
||||||
no_port_entry = MOCK_SPEAKER_CONFIG.copy()
|
|
||||||
no_port_entry[CONF_HOST] = no_port_entry[CONF_HOST].split(":")[0]
|
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data=no_port_entry, options={CONF_VOLUME_STEP: VOLUME_STEP}
|
|
||||||
)
|
|
||||||
entry.add_to_hass(hass)
|
|
||||||
fail_entry = MOCK_SPEAKER_CONFIG.copy()
|
|
||||||
fail_entry[CONF_NAME] = "newtestname"
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN, context={"source": SOURCE_USER}, data=fail_entry
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
||||||
assert result["errors"] == {CONF_HOST: "host_exists"}
|
|
||||||
|
|
||||||
|
|
||||||
async def test_user_name_already_configured(
|
|
||||||
hass: HomeAssistantType,
|
|
||||||
vizio_connect: pytest.fixture,
|
|
||||||
vizio_bypass_setup: pytest.fixture,
|
|
||||||
) -> None:
|
|
||||||
"""Test name is already configured during user setup."""
|
|
||||||
entry = MockConfigEntry(
|
|
||||||
domain=DOMAIN, data=MOCK_SPEAKER_CONFIG, options={CONF_VOLUME_STEP: VOLUME_STEP}
|
|
||||||
)
|
|
||||||
entry.add_to_hass(hass)
|
|
||||||
|
|
||||||
fail_entry = MOCK_SPEAKER_CONFIG.copy()
|
|
||||||
fail_entry[CONF_HOST] = "0.0.0.0"
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN, context={"source": SOURCE_USER}, data=fail_entry
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
|
||||||
assert result["errors"] == {CONF_NAME: "name_exists"}
|
|
||||||
|
|
||||||
|
|
||||||
async def test_user_esn_already_exists(
|
|
||||||
hass: HomeAssistantType,
|
|
||||||
vizio_connect: pytest.fixture,
|
|
||||||
vizio_bypass_setup: pytest.fixture,
|
|
||||||
) -> None:
|
|
||||||
"""Test ESN is already configured with different host and name during user setup."""
|
|
||||||
# Set up new entry
|
# Set up new entry
|
||||||
MockConfigEntry(
|
MockConfigEntry(
|
||||||
domain=DOMAIN, data=MOCK_SPEAKER_CONFIG, unique_id=UNIQUE_ID
|
domain=DOMAIN, data=MOCK_SPEAKER_CONFIG, unique_id=UNIQUE_ID
|
||||||
|
@ -303,14 +259,26 @@ async def test_user_esn_already_exists(
|
||||||
DOMAIN, context={"source": SOURCE_USER}, data=fail_entry
|
DOMAIN, context={"source": SOURCE_USER}, data=fail_entry
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["reason"] == "already_configured"
|
assert result["errors"] == {CONF_HOST: "existing_config_entry_found"}
|
||||||
|
|
||||||
|
|
||||||
async def test_user_error_on_could_not_connect(
|
async def test_user_error_on_could_not_connect(
|
||||||
|
hass: HomeAssistantType, vizio_no_unique_id: pytest.fixture
|
||||||
|
) -> None:
|
||||||
|
"""Test with could_not_connect during user setup due to no connectivity."""
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": SOURCE_USER}, data=MOCK_USER_VALID_TV_CONFIG
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["errors"] == {CONF_HOST: "cannot_connect"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user_error_on_could_not_connect_invalid_token(
|
||||||
hass: HomeAssistantType, vizio_cant_connect: pytest.fixture
|
hass: HomeAssistantType, vizio_cant_connect: pytest.fixture
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test with could_not_connect during user_setup."""
|
"""Test with could_not_connect during user setup due to invalid token."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_USER}, data=MOCK_USER_VALID_TV_CONFIG
|
DOMAIN, context={"source": SOURCE_USER}, data=MOCK_USER_VALID_TV_CONFIG
|
||||||
)
|
)
|
||||||
|
@ -683,6 +651,7 @@ async def test_import_error(
|
||||||
domain=DOMAIN,
|
domain=DOMAIN,
|
||||||
data=vol.Schema(VIZIO_SCHEMA)(MOCK_SPEAKER_CONFIG),
|
data=vol.Schema(VIZIO_SCHEMA)(MOCK_SPEAKER_CONFIG),
|
||||||
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||||
|
unique_id=UNIQUE_ID,
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
fail_entry = MOCK_SPEAKER_CONFIG.copy()
|
fail_entry = MOCK_SPEAKER_CONFIG.copy()
|
||||||
|
@ -763,10 +732,14 @@ async def test_zeroconf_flow_already_configured(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
vizio_connect: pytest.fixture,
|
vizio_connect: pytest.fixture,
|
||||||
vizio_bypass_setup: pytest.fixture,
|
vizio_bypass_setup: pytest.fixture,
|
||||||
|
vizio_guess_device_type: pytest.fixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test entity is already configured during zeroconf setup."""
|
"""Test entity is already configured during zeroconf setup."""
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=DOMAIN, data=MOCK_SPEAKER_CONFIG, options={CONF_VOLUME_STEP: VOLUME_STEP}
|
domain=DOMAIN,
|
||||||
|
data=MOCK_SPEAKER_CONFIG,
|
||||||
|
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||||
|
unique_id=UNIQUE_ID,
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
@ -778,7 +751,7 @@ async def test_zeroconf_flow_already_configured(
|
||||||
|
|
||||||
# Flow should abort because device is already setup
|
# Flow should abort because device is already setup
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
assert result["reason"] == "already_configured_device"
|
assert result["reason"] == "already_configured"
|
||||||
|
|
||||||
|
|
||||||
async def test_zeroconf_dupe_fail(
|
async def test_zeroconf_dupe_fail(
|
||||||
|
@ -842,7 +815,7 @@ async def test_zeroconf_abort_when_ignored(
|
||||||
data=MOCK_SPEAKER_CONFIG,
|
data=MOCK_SPEAKER_CONFIG,
|
||||||
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||||
source=SOURCE_IGNORE,
|
source=SOURCE_IGNORE,
|
||||||
unique_id=ZEROCONF_HOST,
|
unique_id=UNIQUE_ID,
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
@ -860,12 +833,16 @@ async def test_zeroconf_flow_already_configured_hostname(
|
||||||
vizio_connect: pytest.fixture,
|
vizio_connect: pytest.fixture,
|
||||||
vizio_bypass_setup: pytest.fixture,
|
vizio_bypass_setup: pytest.fixture,
|
||||||
vizio_hostname_check: pytest.fixture,
|
vizio_hostname_check: pytest.fixture,
|
||||||
|
vizio_guess_device_type: pytest.fixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test entity is already configured during zeroconf setup when existing entry uses hostname."""
|
"""Test entity is already configured during zeroconf setup when existing entry uses hostname."""
|
||||||
config = MOCK_SPEAKER_CONFIG.copy()
|
config = MOCK_SPEAKER_CONFIG.copy()
|
||||||
config[CONF_HOST] = "hostname"
|
config[CONF_HOST] = "hostname"
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=DOMAIN, data=config, options={CONF_VOLUME_STEP: VOLUME_STEP}
|
domain=DOMAIN,
|
||||||
|
data=config,
|
||||||
|
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||||
|
unique_id=UNIQUE_ID,
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
@ -877,7 +854,7 @@ async def test_zeroconf_flow_already_configured_hostname(
|
||||||
|
|
||||||
# Flow should abort because device is already setup
|
# Flow should abort because device is already setup
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
assert result["reason"] == "already_configured_device"
|
assert result["reason"] == "already_configured"
|
||||||
|
|
||||||
|
|
||||||
async def test_import_flow_already_configured_hostname(
|
async def test_import_flow_already_configured_hostname(
|
||||||
|
|
Loading…
Reference in New Issue