mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 17:27:52 +00:00
Use default media player device classes for vizio component (#30802)
* use media player defined device classes instead of custom ones, add options flow test, add timeout options parameter * make options update error more generic * fix config flow options update logic * simplify logic for options update during import * use platform list for load and unload * update private config flow function name and description * fix grammar in strings.json * update mock config variable names to be more accurate * remove timeout conf option, create device_class property * update requirements * update .coveragerc to indicate that config_flow has tests * fix source of device_class property and move constants to const.py * fix grammar in error message * remove redundant device check in async_setup_entry since device connection is checked during config flow * revert change to async_setup_entry, raise ConfigEntryNotReady if device can't be connected to * update error text * add more context to error text
This commit is contained in:
parent
52cee84c2c
commit
8630a076a7
@ -782,7 +782,9 @@ omit =
|
||||
homeassistant/components/viaggiatreno/sensor.py
|
||||
homeassistant/components/vicare/*
|
||||
homeassistant/components/vivotek/camera.py
|
||||
homeassistant/components/vizio/*
|
||||
homeassistant/components/vizio/__init__.py
|
||||
homeassistant/components/vizio/const.py
|
||||
homeassistant/components/vizio/media_player.py
|
||||
homeassistant/components/vlc/media_player.py
|
||||
homeassistant/components/vlc_telnet/media_player.py
|
||||
homeassistant/components/volkszaehler/sensor.py
|
||||
|
@ -1,49 +1,30 @@
|
||||
"""The vizio component."""
|
||||
import asyncio
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.media_player import DEVICE_CLASS_TV
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_ACCESS_TOKEN,
|
||||
CONF_DEVICE_CLASS,
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
)
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_DEVICE_CLASS
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||
|
||||
from .const import (
|
||||
CONF_VOLUME_STEP,
|
||||
DEFAULT_DEVICE_CLASS,
|
||||
DEFAULT_NAME,
|
||||
DEFAULT_VOLUME_STEP,
|
||||
DOMAIN,
|
||||
)
|
||||
from .const import DOMAIN, VIZIO_SCHEMA
|
||||
|
||||
|
||||
def validate_auth(config: ConfigType) -> ConfigType:
|
||||
"""Validate presence of CONF_ACCESS_TOKEN when CONF_DEVICE_CLASS=tv."""
|
||||
"""Validate presence of CONF_ACCESS_TOKEN when CONF_DEVICE_CLASS == DEVICE_CLASS_TV."""
|
||||
token = config.get(CONF_ACCESS_TOKEN)
|
||||
if config[CONF_DEVICE_CLASS] == "tv" and not token:
|
||||
if config[CONF_DEVICE_CLASS] == DEVICE_CLASS_TV and not token:
|
||||
raise vol.Invalid(
|
||||
f"When '{CONF_DEVICE_CLASS}' is 'tv' then '{CONF_ACCESS_TOKEN}' is required.",
|
||||
f"When '{CONF_DEVICE_CLASS}' is '{DEVICE_CLASS_TV}' then "
|
||||
f"'{CONF_ACCESS_TOKEN}' is required.",
|
||||
path=[CONF_ACCESS_TOKEN],
|
||||
)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
VIZIO_SCHEMA = {
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_ACCESS_TOKEN): cv.string,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_DEVICE_CLASS, default=DEFAULT_DEVICE_CLASS): vol.All(
|
||||
cv.string, vol.Lower, vol.In(["tv", "soundbar"])
|
||||
),
|
||||
vol.Optional(CONF_VOLUME_STEP, default=DEFAULT_VOLUME_STEP): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1, max=10)
|
||||
),
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.All(
|
||||
@ -53,6 +34,8 @@ CONFIG_SCHEMA = vol.Schema(
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
PLATFORMS = ["media_player"]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
|
||||
"""Component setup, run import config flow for each entry in config."""
|
||||
@ -69,15 +52,23 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool:
|
||||
"""Load the saved entities."""
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(entry, "media_player")
|
||||
)
|
||||
for platform in PLATFORMS:
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(entry, platform)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
await hass.config_entries.async_forward_entry_unload(entry, "media_player")
|
||||
unload_ok = all(
|
||||
await asyncio.gather(
|
||||
*[
|
||||
hass.config_entries.async_forward_entry_unload(entry, platform)
|
||||
for platform in PLATFORMS
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
return True
|
||||
return unload_ok
|
||||
|
@ -6,6 +6,7 @@ from pyvizio import VizioAsync
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.media_player import DEVICE_CLASS_SPEAKER, DEVICE_CLASS_TV
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_ACCESS_TOKEN,
|
||||
@ -27,8 +28,8 @@ from .const import (
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def update_schema_defaults(input_dict: Dict[str, Any]) -> vol.Schema:
|
||||
"""Update schema defaults based on user input/config dict. Retains info already provided for future form views."""
|
||||
def _config_flow_schema(input_dict: Dict[str, Any]) -> vol.Schema:
|
||||
"""Return schema defaults based on user input/config dict. Retain info already provided for future form views by setting them as defaults in schema."""
|
||||
return vol.Schema(
|
||||
{
|
||||
vol.Required(
|
||||
@ -38,7 +39,7 @@ def update_schema_defaults(input_dict: Dict[str, Any]) -> vol.Schema:
|
||||
vol.Optional(
|
||||
CONF_DEVICE_CLASS,
|
||||
default=input_dict.get(CONF_DEVICE_CLASS, DEFAULT_DEVICE_CLASS),
|
||||
): vol.All(str, vol.Lower, vol.In(["tv", "soundbar"])),
|
||||
): vol.All(str, vol.Lower, vol.In([DEVICE_CLASS_TV, DEVICE_CLASS_SPEAKER])),
|
||||
vol.Optional(
|
||||
CONF_ACCESS_TOKEN, default=input_dict.get(CONF_ACCESS_TOKEN, "")
|
||||
): str,
|
||||
@ -72,7 +73,7 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
|
||||
if user_input is not None:
|
||||
# Store current values in case setup fails and user needs to edit
|
||||
self.user_schema = update_schema_defaults(user_input)
|
||||
self.user_schema = _config_flow_schema(user_input)
|
||||
|
||||
# Check if new config entry matches any existing config entries
|
||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||
@ -116,7 +117,7 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
title=user_input[CONF_NAME], data=user_input
|
||||
)
|
||||
|
||||
schema = self.user_schema or self.import_schema or update_schema_defaults({})
|
||||
schema = self.user_schema or self.import_schema or _config_flow_schema({})
|
||||
|
||||
return self.async_show_form(step_id="user", data_schema=schema, errors=errors)
|
||||
|
||||
@ -127,20 +128,23 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
if entry.data[CONF_HOST] == import_config[CONF_HOST] and entry.data[
|
||||
CONF_NAME
|
||||
] == import_config.get(CONF_NAME):
|
||||
new_options = {}
|
||||
|
||||
if entry.data[CONF_VOLUME_STEP] != import_config[CONF_VOLUME_STEP]:
|
||||
new_volume_step = {
|
||||
CONF_VOLUME_STEP: import_config[CONF_VOLUME_STEP]
|
||||
}
|
||||
new_options[CONF_VOLUME_STEP] = import_config[CONF_VOLUME_STEP]
|
||||
|
||||
if new_options:
|
||||
self.hass.config_entries.async_update_entry(
|
||||
entry=entry,
|
||||
data=entry.data.copy().update(new_volume_step),
|
||||
options=entry.options.copy().update(new_volume_step),
|
||||
data=entry.data.copy().update(new_options),
|
||||
options=entry.options.copy().update(new_options),
|
||||
)
|
||||
return self.async_abort(reason="updated_volume_step")
|
||||
return self.async_abort(reason="updated_options")
|
||||
|
||||
return self.async_abort(reason="already_setup")
|
||||
|
||||
# Store import values in case setup fails so user can see error
|
||||
self.import_schema = update_schema_defaults(import_config)
|
||||
self.import_schema = _config_flow_schema(import_config)
|
||||
|
||||
return await self.async_step_user(user_input=import_config)
|
||||
|
||||
|
@ -1,11 +1,76 @@
|
||||
"""Constants used by vizio component."""
|
||||
from datetime import timedelta
|
||||
|
||||
from pyvizio.const import (
|
||||
DEVICE_CLASS_SPEAKER as VIZIO_DEVICE_CLASS_SPEAKER,
|
||||
DEVICE_CLASS_TV as VIZIO_DEVICE_CLASS_TV,
|
||||
)
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.media_player import DEVICE_CLASS_SPEAKER, DEVICE_CLASS_TV
|
||||
from homeassistant.components.media_player.const import (
|
||||
SUPPORT_NEXT_TRACK,
|
||||
SUPPORT_PREVIOUS_TRACK,
|
||||
SUPPORT_SELECT_SOURCE,
|
||||
SUPPORT_TURN_OFF,
|
||||
SUPPORT_TURN_ON,
|
||||
SUPPORT_VOLUME_MUTE,
|
||||
SUPPORT_VOLUME_SET,
|
||||
SUPPORT_VOLUME_STEP,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_ACCESS_TOKEN,
|
||||
CONF_DEVICE_CLASS,
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
CONF_VOLUME_STEP = "volume_step"
|
||||
|
||||
DEFAULT_DEVICE_CLASS = DEVICE_CLASS_TV
|
||||
DEFAULT_NAME = "Vizio SmartCast"
|
||||
DEFAULT_VOLUME_STEP = 1
|
||||
DEFAULT_DEVICE_CLASS = "tv"
|
||||
|
||||
DEVICE_ID = "pyvizio"
|
||||
|
||||
DOMAIN = "vizio"
|
||||
ICON = {DEVICE_CLASS_TV: "mdi:television", DEVICE_CLASS_SPEAKER: "mdi:speaker"}
|
||||
|
||||
ICON = {"tv": "mdi:television", "soundbar": "mdi:speaker"}
|
||||
COMMON_SUPPORTED_COMMANDS = (
|
||||
SUPPORT_SELECT_SOURCE
|
||||
| SUPPORT_TURN_ON
|
||||
| SUPPORT_TURN_OFF
|
||||
| SUPPORT_VOLUME_MUTE
|
||||
| SUPPORT_VOLUME_SET
|
||||
| SUPPORT_VOLUME_STEP
|
||||
)
|
||||
|
||||
SUPPORTED_COMMANDS = {
|
||||
DEVICE_CLASS_SPEAKER: COMMON_SUPPORTED_COMMANDS,
|
||||
DEVICE_CLASS_TV: (
|
||||
COMMON_SUPPORTED_COMMANDS | SUPPORT_NEXT_TRACK | SUPPORT_PREVIOUS_TRACK
|
||||
),
|
||||
}
|
||||
|
||||
# Since Vizio component relies on device class, this dict will ensure that changes to
|
||||
# the values of DEVICE_CLASS_SPEAKER or DEVICE_CLASS_TV don't require changes to pyvizio.
|
||||
VIZIO_DEVICE_CLASSES = {
|
||||
DEVICE_CLASS_SPEAKER: VIZIO_DEVICE_CLASS_SPEAKER,
|
||||
DEVICE_CLASS_TV: VIZIO_DEVICE_CLASS_TV,
|
||||
}
|
||||
|
||||
VIZIO_SCHEMA = {
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_ACCESS_TOKEN): cv.string,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_DEVICE_CLASS, default=DEFAULT_DEVICE_CLASS): vol.All(
|
||||
cv.string, vol.Lower, vol.In([DEVICE_CLASS_TV, DEVICE_CLASS_SPEAKER])
|
||||
),
|
||||
vol.Optional(CONF_VOLUME_STEP, default=DEFAULT_VOLUME_STEP): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1, max=10)
|
||||
),
|
||||
}
|
||||
|
||||
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1)
|
||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||
|
@ -1,5 +1,4 @@
|
||||
"""Vizio SmartCast Device support."""
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Callable, List
|
||||
|
||||
@ -7,16 +6,6 @@ from pyvizio import VizioAsync
|
||||
|
||||
from homeassistant import util
|
||||
from homeassistant.components.media_player import MediaPlayerDevice
|
||||
from homeassistant.components.media_player.const import (
|
||||
SUPPORT_NEXT_TRACK,
|
||||
SUPPORT_PREVIOUS_TRACK,
|
||||
SUPPORT_SELECT_SOURCE,
|
||||
SUPPORT_TURN_OFF,
|
||||
SUPPORT_TURN_ON,
|
||||
SUPPORT_VOLUME_MUTE,
|
||||
SUPPORT_VOLUME_SET,
|
||||
SUPPORT_VOLUME_STEP,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_ACCESS_TOKEN,
|
||||
@ -35,29 +24,23 @@ from homeassistant.helpers.dispatcher import (
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from .const import CONF_VOLUME_STEP, DEFAULT_VOLUME_STEP, DEVICE_ID, DOMAIN, ICON
|
||||
from .const import (
|
||||
CONF_VOLUME_STEP,
|
||||
DEFAULT_VOLUME_STEP,
|
||||
DEVICE_ID,
|
||||
DOMAIN,
|
||||
ICON,
|
||||
MIN_TIME_BETWEEN_FORCED_SCANS,
|
||||
MIN_TIME_BETWEEN_SCANS,
|
||||
SUPPORTED_COMMANDS,
|
||||
VIZIO_DEVICE_CLASSES,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1)
|
||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
COMMON_SUPPORTED_COMMANDS = (
|
||||
SUPPORT_SELECT_SOURCE
|
||||
| SUPPORT_TURN_ON
|
||||
| SUPPORT_TURN_OFF
|
||||
| SUPPORT_VOLUME_MUTE
|
||||
| SUPPORT_VOLUME_SET
|
||||
| SUPPORT_VOLUME_STEP
|
||||
)
|
||||
|
||||
SUPPORTED_COMMANDS = {
|
||||
"soundbar": COMMON_SUPPORTED_COMMANDS,
|
||||
"tv": (COMMON_SUPPORTED_COMMANDS | SUPPORT_NEXT_TRACK | SUPPORT_PREVIOUS_TRACK),
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistantType,
|
||||
@ -68,10 +51,10 @@ async def async_setup_entry(
|
||||
host = config_entry.data[CONF_HOST]
|
||||
token = config_entry.data.get(CONF_ACCESS_TOKEN)
|
||||
name = config_entry.data[CONF_NAME]
|
||||
device_type = config_entry.data[CONF_DEVICE_CLASS]
|
||||
device_class = config_entry.data[CONF_DEVICE_CLASS]
|
||||
|
||||
# If config entry options not set up, set them up, otherwise assign values managed in options
|
||||
if CONF_VOLUME_STEP not in config_entry.options:
|
||||
if not config_entry.options:
|
||||
volume_step = config_entry.data.get(CONF_VOLUME_STEP, DEFAULT_VOLUME_STEP)
|
||||
hass.config_entries.async_update_entry(
|
||||
config_entry, options={CONF_VOLUME_STEP: volume_step}
|
||||
@ -84,22 +67,24 @@ async def async_setup_entry(
|
||||
host,
|
||||
name,
|
||||
token,
|
||||
device_type,
|
||||
VIZIO_DEVICE_CLASSES[device_class],
|
||||
session=async_get_clientsession(hass, False),
|
||||
)
|
||||
|
||||
if not await device.can_connect():
|
||||
fail_auth_msg = ""
|
||||
if token:
|
||||
fail_auth_msg = ", auth token is correct"
|
||||
fail_auth_msg = "and auth token '{token}' are correct."
|
||||
else:
|
||||
fail_auth_msg = "is correct."
|
||||
_LOGGER.error(
|
||||
"Failed to set up Vizio platform, please check if host "
|
||||
"is valid and available, device type is correct%s",
|
||||
"Failed to connect to Vizio device, please check if host '{host}'"
|
||||
"is valid and available. Also check if device class '{device_class}' %s",
|
||||
fail_auth_msg,
|
||||
)
|
||||
raise PlatformNotReady
|
||||
|
||||
entity = VizioDevice(config_entry, device, name, volume_step, device_type)
|
||||
entity = VizioDevice(config_entry, device, name, volume_step, device_class)
|
||||
|
||||
async_add_entities([entity], True)
|
||||
|
||||
@ -113,7 +98,7 @@ class VizioDevice(MediaPlayerDevice):
|
||||
device: VizioAsync,
|
||||
name: str,
|
||||
volume_step: int,
|
||||
device_type: str,
|
||||
device_class: str,
|
||||
) -> None:
|
||||
"""Initialize Vizio device."""
|
||||
self._config_entry = config_entry
|
||||
@ -125,11 +110,11 @@ class VizioDevice(MediaPlayerDevice):
|
||||
self._volume_step = volume_step
|
||||
self._current_input = None
|
||||
self._available_inputs = None
|
||||
self._device_type = device_type
|
||||
self._supported_commands = SUPPORTED_COMMANDS[device_type]
|
||||
self._device_class = device_class
|
||||
self._supported_commands = SUPPORTED_COMMANDS[device_class]
|
||||
self._device = device
|
||||
self._max_volume = float(self._device.get_max_volume())
|
||||
self._icon = ICON[device_type]
|
||||
self._icon = ICON[device_class]
|
||||
self._available = True
|
||||
|
||||
@util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS)
|
||||
@ -169,7 +154,8 @@ class VizioDevice(MediaPlayerDevice):
|
||||
hass: HomeAssistantType, config_entry: ConfigEntry
|
||||
) -> None:
|
||||
"""Send update event when when Vizio config entry is updated."""
|
||||
# Move this method to component level if another entity ever gets added for a single config entry. See here: https://github.com/home-assistant/home-assistant/pull/30653#discussion_r366426121
|
||||
# Move this method to component level if another entity ever gets added for a single config entry.
|
||||
# See here: https://github.com/home-assistant/home-assistant/pull/30653#discussion_r366426121
|
||||
async_dispatcher_send(hass, config_entry.entry_id, config_entry)
|
||||
|
||||
async def _async_update_options(self, config_entry: ConfigEntry) -> None:
|
||||
@ -253,6 +239,11 @@ class VizioDevice(MediaPlayerDevice):
|
||||
"manufacturer": "VIZIO",
|
||||
}
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return device class for entity."""
|
||||
return self._device_class
|
||||
|
||||
async def async_turn_on(self) -> None:
|
||||
"""Turn the device on."""
|
||||
await self._device.pow_on()
|
||||
|
@ -23,7 +23,7 @@
|
||||
"already_setup": "This entry has already been setup.",
|
||||
"host_exists": "Vizio component with host already configured.",
|
||||
"name_exists": "Vizio component with name already configured.",
|
||||
"updated_volume_step": "This entry has already been setup but the volume step size in the config does not match the config entry so the config entry has been updated accordingly."
|
||||
"updated_options": "This entry has already been setup but the options defined in the config do not match the previously imported options values so the config entry has been updated accordingly."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
@ -32,7 +32,8 @@
|
||||
"init": {
|
||||
"title": "Update Vizo SmartCast Options",
|
||||
"data": {
|
||||
"volume_step": "Volume Step Size"
|
||||
"volume_step": "Volume Step Size",
|
||||
"timeout": "API Request Timeout (seconds)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,13 @@ import pytest
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.vizio import VIZIO_SCHEMA
|
||||
from homeassistant.components.media_player import DEVICE_CLASS_SPEAKER, DEVICE_CLASS_TV
|
||||
from homeassistant.components.vizio.const import (
|
||||
CONF_VOLUME_STEP,
|
||||
DEFAULT_NAME,
|
||||
DEFAULT_VOLUME_STEP,
|
||||
DOMAIN,
|
||||
VIZIO_SCHEMA,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_ACCESS_TOKEN,
|
||||
@ -27,20 +28,18 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
NAME = "Vizio"
|
||||
HOST = "192.168.1.1:9000"
|
||||
DEVICE_CLASS_TV = "tv"
|
||||
DEVICE_CLASS_SOUNDBAR = "soundbar"
|
||||
ACCESS_TOKEN = "deadbeef"
|
||||
VOLUME_STEP = 2
|
||||
UNIQUE_ID = "testid"
|
||||
|
||||
MOCK_USER_VALID_TV_ENTRY = {
|
||||
MOCK_USER_VALID_TV_CONFIG = {
|
||||
CONF_NAME: NAME,
|
||||
CONF_HOST: HOST,
|
||||
CONF_DEVICE_CLASS: DEVICE_CLASS_TV,
|
||||
CONF_ACCESS_TOKEN: ACCESS_TOKEN,
|
||||
}
|
||||
|
||||
MOCK_IMPORT_VALID_TV_ENTRY = {
|
||||
MOCK_IMPORT_VALID_TV_CONFIG = {
|
||||
CONF_NAME: NAME,
|
||||
CONF_HOST: HOST,
|
||||
CONF_DEVICE_CLASS: DEVICE_CLASS_TV,
|
||||
@ -48,16 +47,16 @@ MOCK_IMPORT_VALID_TV_ENTRY = {
|
||||
CONF_VOLUME_STEP: VOLUME_STEP,
|
||||
}
|
||||
|
||||
MOCK_INVALID_TV_ENTRY = {
|
||||
MOCK_INVALID_TV_CONFIG = {
|
||||
CONF_NAME: NAME,
|
||||
CONF_HOST: HOST,
|
||||
CONF_DEVICE_CLASS: DEVICE_CLASS_TV,
|
||||
}
|
||||
|
||||
MOCK_SOUNDBAR_ENTRY = {
|
||||
MOCK_SPEAKER_CONFIG = {
|
||||
CONF_NAME: NAME,
|
||||
CONF_HOST: HOST,
|
||||
CONF_DEVICE_CLASS: DEVICE_CLASS_SOUNDBAR,
|
||||
CONF_DEVICE_CLASS: DEVICE_CLASS_SPEAKER,
|
||||
}
|
||||
|
||||
|
||||
@ -100,7 +99,7 @@ async def test_user_flow_minimum_fields(hass: HomeAssistantType, vizio_connect)
|
||||
user_input={
|
||||
CONF_NAME: NAME,
|
||||
CONF_HOST: HOST,
|
||||
CONF_DEVICE_CLASS: DEVICE_CLASS_SOUNDBAR,
|
||||
CONF_DEVICE_CLASS: DEVICE_CLASS_SPEAKER,
|
||||
},
|
||||
)
|
||||
|
||||
@ -108,7 +107,7 @@ async def test_user_flow_minimum_fields(hass: HomeAssistantType, vizio_connect)
|
||||
assert result["title"] == NAME
|
||||
assert result["data"][CONF_NAME] == NAME
|
||||
assert result["data"][CONF_HOST] == HOST
|
||||
assert result["data"][CONF_DEVICE_CLASS] == DEVICE_CLASS_SOUNDBAR
|
||||
assert result["data"][CONF_DEVICE_CLASS] == DEVICE_CLASS_SPEAKER
|
||||
|
||||
|
||||
async def test_user_flow_all_fields(hass: HomeAssistantType, vizio_connect) -> None:
|
||||
@ -139,17 +138,40 @@ async def test_user_flow_all_fields(hass: HomeAssistantType, vizio_connect) -> N
|
||||
assert result["data"][CONF_ACCESS_TOKEN] == ACCESS_TOKEN
|
||||
|
||||
|
||||
async def test_options_flow(hass: HomeAssistantType) -> None:
|
||||
"""Test options config flow."""
|
||||
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_SPEAKER_CONFIG)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
assert not entry.options
|
||||
|
||||
result = await hass.config_entries.options.async_init(
|
||||
entry.entry_id, context={"source": "test"}, data=None
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["step_id"] == "init"
|
||||
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"], user_input={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == ""
|
||||
assert result["data"][CONF_VOLUME_STEP] == VOLUME_STEP
|
||||
|
||||
|
||||
async def test_user_host_already_configured(
|
||||
hass: HomeAssistantType, vizio_connect
|
||||
) -> None:
|
||||
"""Test host is already configured during user setup."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data=MOCK_SOUNDBAR_ENTRY,
|
||||
data=MOCK_SPEAKER_CONFIG,
|
||||
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
fail_entry = MOCK_SOUNDBAR_ENTRY.copy()
|
||||
fail_entry = MOCK_SPEAKER_CONFIG.copy()
|
||||
fail_entry[CONF_NAME] = "newtestname"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@ -160,7 +182,7 @@ async def test_user_host_already_configured(
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input=fail_entry,
|
||||
result["flow_id"], user_input=fail_entry
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
@ -173,12 +195,12 @@ async def test_user_name_already_configured(
|
||||
"""Test name is already configured during user setup."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data=MOCK_SOUNDBAR_ENTRY,
|
||||
data=MOCK_SPEAKER_CONFIG,
|
||||
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
fail_entry = MOCK_SOUNDBAR_ENTRY.copy()
|
||||
fail_entry = MOCK_SPEAKER_CONFIG.copy()
|
||||
fail_entry[CONF_HOST] = "0.0.0.0"
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
@ -207,7 +229,7 @@ async def test_user_error_on_could_not_connect(
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], MOCK_USER_VALID_TV_ENTRY
|
||||
result["flow_id"], MOCK_USER_VALID_TV_CONFIG
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["errors"] == {"base": "cant_connect"}
|
||||
@ -225,7 +247,7 @@ async def test_user_error_on_tv_needs_token(
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], MOCK_INVALID_TV_ENTRY
|
||||
result["flow_id"], MOCK_INVALID_TV_CONFIG
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
@ -240,7 +262,7 @@ async def test_import_flow_minimum_fields(
|
||||
DOMAIN,
|
||||
context={"source": "import"},
|
||||
data=vol.Schema(VIZIO_SCHEMA)(
|
||||
{CONF_HOST: HOST, CONF_DEVICE_CLASS: DEVICE_CLASS_SOUNDBAR}
|
||||
{CONF_HOST: HOST, CONF_DEVICE_CLASS: DEVICE_CLASS_SPEAKER}
|
||||
),
|
||||
)
|
||||
|
||||
@ -248,7 +270,7 @@ async def test_import_flow_minimum_fields(
|
||||
assert result["title"] == DEFAULT_NAME
|
||||
assert result["data"][CONF_NAME] == DEFAULT_NAME
|
||||
assert result["data"][CONF_HOST] == HOST
|
||||
assert result["data"][CONF_DEVICE_CLASS] == DEVICE_CLASS_SOUNDBAR
|
||||
assert result["data"][CONF_DEVICE_CLASS] == DEVICE_CLASS_SPEAKER
|
||||
assert result["data"][CONF_VOLUME_STEP] == DEFAULT_VOLUME_STEP
|
||||
|
||||
|
||||
@ -257,7 +279,7 @@ async def test_import_flow_all_fields(hass: HomeAssistantType, vizio_connect) ->
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": "import"},
|
||||
data=vol.Schema(VIZIO_SCHEMA)(MOCK_IMPORT_VALID_TV_ENTRY),
|
||||
data=vol.Schema(VIZIO_SCHEMA)(MOCK_IMPORT_VALID_TV_CONFIG),
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
@ -275,11 +297,11 @@ async def test_import_entity_already_configured(
|
||||
"""Test entity is already configured during import setup."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
data=vol.Schema(VIZIO_SCHEMA)(MOCK_SOUNDBAR_ENTRY),
|
||||
data=vol.Schema(VIZIO_SCHEMA)(MOCK_SPEAKER_CONFIG),
|
||||
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
fail_entry = vol.Schema(VIZIO_SCHEMA)(MOCK_SOUNDBAR_ENTRY.copy())
|
||||
fail_entry = vol.Schema(VIZIO_SCHEMA)(MOCK_SPEAKER_CONFIG.copy())
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": "import"}, data=fail_entry
|
||||
|
Loading…
x
Reference in New Issue
Block a user