diff --git a/homeassistant/components/vizio/__init__.py b/homeassistant/components/vizio/__init__.py index ac02698dbfd..436ad829d94 100644 --- a/homeassistant/components/vizio/__init__.py +++ b/homeassistant/components/vizio/__init__.py @@ -50,22 +50,24 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: return True -async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: +async def async_setup_entry(hass: HomeAssistantType, config_entry: ConfigEntry) -> bool: """Load the saved entities.""" for platform in PLATFORMS: hass.async_create_task( - hass.config_entries.async_forward_entry_setup(entry, platform) + hass.config_entries.async_forward_entry_setup(config_entry, platform) ) return True -async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: +async def async_unload_entry( + hass: HomeAssistantType, config_entry: ConfigEntry +) -> bool: """Unload a config entry.""" unload_ok = all( await asyncio.gather( *[ - hass.config_entries.async_forward_entry_unload(entry, platform) + hass.config_entries.async_forward_entry_unload(config_entry, platform) for platform in PLATFORMS ] ) diff --git a/homeassistant/components/vizio/config_flow.py b/homeassistant/components/vizio/config_flow.py index a02ae22a46b..5500ec3db94 100644 --- a/homeassistant/components/vizio/config_flow.py +++ b/homeassistant/components/vizio/config_flow.py @@ -30,8 +30,11 @@ from .const import ( _LOGGER = logging.getLogger(__name__) -def _config_flow_schema(input_dict: Dict[str, Any]) -> vol.Schema: +def _get_config_flow_schema(input_dict: Dict[str, Any] = None) -> 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.""" + if input_dict is None: + input_dict = {} + return vol.Schema( { vol.Required( @@ -50,6 +53,32 @@ def _config_flow_schema(input_dict: Dict[str, Any]) -> vol.Schema: ) +class VizioOptionsConfigFlow(config_entries.OptionsFlow): + """Handle Transmission client options.""" + + def __init__(self, config_entry: ConfigEntry) -> None: + """Initialize vizio options flow.""" + self.config_entry = config_entry + + async def async_step_init( + self, user_input: Dict[str, Any] = None + ) -> Dict[str, Any]: + """Manage the vizio options.""" + if user_input is not None: + return self.async_create_entry(title="", data=user_input) + + options = { + vol.Optional( + CONF_VOLUME_STEP, + default=self.config_entry.options.get( + CONF_VOLUME_STEP, DEFAULT_VOLUME_STEP + ), + ): vol.All(vol.Coerce(int), vol.Range(min=1, max=10)) + } + + return self.async_show_form(step_id="init", data_schema=vol.Schema(options)) + + class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a Vizio config flow.""" @@ -58,14 +87,13 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): @staticmethod @callback - def async_get_options_flow(config_entry): + def async_get_options_flow(config_entry: ConfigEntry) -> VizioOptionsConfigFlow: """Get the options flow for this handler.""" return VizioOptionsConfigFlow(config_entry) def __init__(self) -> None: """Initialize config flow.""" - self.import_schema = None - self.user_schema = None + self._user_schema = None self._must_show_form = None async def async_step_user( @@ -76,7 +104,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 = _config_flow_schema(user_input) + self._user_schema = _get_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): @@ -129,7 +157,7 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): ) # Use user_input params as default values for schema if user_input is non-empty, otherwise use default schema - schema = self.user_schema or self.import_schema or _config_flow_schema({}) + schema = self._user_schema or _get_config_flow_schema() return self.async_show_form(step_id="user", data_schema=schema, errors=errors) @@ -158,9 +186,6 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): return self.async_abort(reason="already_setup") - # Store import values in case setup fails so user can see error - self.import_schema = _config_flow_schema(import_config) - return await self.async_step_user(user_input=import_config) async def async_step_zeroconf( @@ -190,29 +215,3 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): self._must_show_form = True return await self.async_step_user(user_input=discovery_info) - - -class VizioOptionsConfigFlow(config_entries.OptionsFlow): - """Handle Transmission client options.""" - - def __init__(self, config_entry: ConfigEntry) -> None: - """Initialize vizio options flow.""" - self.config_entry = config_entry - - async def async_step_init( - self, user_input: Dict[str, Any] = None - ) -> Dict[str, Any]: - """Manage the vizio options.""" - if user_input is not None: - return self.async_create_entry(title="", data=user_input) - - options = { - vol.Optional( - CONF_VOLUME_STEP, - default=self.config_entry.options.get( - CONF_VOLUME_STEP, DEFAULT_VOLUME_STEP - ), - ): vol.All(vol.Coerce(int), vol.Range(min=1, max=10)) - } - - return self.async_show_form(step_id="init", data_schema=vol.Schema(options)) diff --git a/homeassistant/components/vizio/media_player.py b/homeassistant/components/vizio/media_player.py index d143c4232bf..000d1baec2d 100644 --- a/homeassistant/components/vizio/media_player.py +++ b/homeassistant/components/vizio/media_player.py @@ -67,8 +67,8 @@ async def async_setup_entry( DEVICE_ID, host, name, - token, - VIZIO_DEVICE_CLASSES[device_class], + auth_token=token, + device_type=VIZIO_DEVICE_CLASSES[device_class], session=async_get_clientsession(hass, False), timeout=DEFAULT_TIMEOUT, ) @@ -86,9 +86,9 @@ async def async_setup_entry( ) raise PlatformNotReady - entity = VizioDevice(config_entry, device, name, volume_step, device_class) + entity = VizioDevice(config_entry, device, name, volume_step, device_class,) - async_add_entities([entity], True) + async_add_entities([entity], update_before_add=True) class VizioDevice(MediaPlayerDevice): @@ -122,7 +122,7 @@ class VizioDevice(MediaPlayerDevice): @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) async def async_update(self) -> None: """Retrieve latest state of the device.""" - is_on = await self._device.get_power_state(False) + is_on = await self._device.get_power_state(log_api_exception=False) if is_on is None: self._available = False @@ -139,15 +139,15 @@ class VizioDevice(MediaPlayerDevice): self._state = STATE_ON - volume = await self._device.get_current_volume(False) + volume = await self._device.get_current_volume(log_api_exception=False) if volume is not None: self._volume_level = float(volume) / self._max_volume - input_ = await self._device.get_current_input(False) + input_ = await self._device.get_current_input(log_api_exception=False) if input_ is not None: self._current_input = input_.meta_name - inputs = await self._device.get_inputs(False) + inputs = await self._device.get_inputs(log_api_exception=False) if inputs is not None: self._available_inputs = [input_.name for input_ in inputs] @@ -275,7 +275,7 @@ class VizioDevice(MediaPlayerDevice): async def async_volume_up(self) -> None: """Increasing volume of the device.""" - await self._device.vol_up(self._volume_step) + await self._device.vol_up(num=self._volume_step) if self._volume_level is not None: self._volume_level = min( @@ -284,7 +284,7 @@ class VizioDevice(MediaPlayerDevice): async def async_volume_down(self) -> None: """Decreasing volume of the device.""" - await self._device.vol_down(self._volume_step) + await self._device.vol_down(num=self._volume_step) if self._volume_level is not None: self._volume_level = max( @@ -296,9 +296,10 @@ class VizioDevice(MediaPlayerDevice): if self._volume_level is not None: if volume > self._volume_level: num = int(self._max_volume * (volume - self._volume_level)) - await self._device.vol_up(num) + await self._device.vol_up(num=num) self._volume_level = volume + elif volume < self._volume_level: num = int(self._max_volume * (self._volume_level - volume)) - await self._device.vol_down(num) + await self._device.vol_down(num=num) self._volume_level = volume diff --git a/tests/components/vizio/test_config_flow.py b/tests/components/vizio/test_config_flow.py index 196ef35469d..c82c7a8de0f 100644 --- a/tests/components/vizio/test_config_flow.py +++ b/tests/components/vizio/test_config_flow.py @@ -129,7 +129,9 @@ def vizio_cant_connect_fixture(): async def test_user_flow_minimum_fields( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, ) -> None: """Test user config flow with minimum fields.""" # test form shows @@ -156,7 +158,9 @@ async def test_user_flow_minimum_fields( async def test_user_flow_all_fields( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, ) -> None: """Test user config flow with all fields.""" # test form shows @@ -192,9 +196,7 @@ async def test_options_flow(hass: HomeAssistantType) -> None: assert not entry.options - result = await hass.config_entries.options.async_init( - entry.entry_id, context={"source": "test"}, data=None - ) + result = await hass.config_entries.options.async_init(entry.entry_id, data=None) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["step_id"] == "init" @@ -209,7 +211,9 @@ async def test_options_flow(hass: HomeAssistantType) -> None: async def test_user_host_already_configured( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, ) -> None: """Test host is already configured during user setup.""" entry = MockConfigEntry( @@ -220,14 +224,7 @@ async def test_user_host_already_configured( fail_entry[CONF_NAME] = "newtestname" result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": SOURCE_USER} - ) - - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - assert result["step_id"] == "user" - - result = await hass.config_entries.flow.async_configure( - result["flow_id"], user_input=fail_entry + DOMAIN, context={"source": SOURCE_USER}, data=fail_entry ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM @@ -235,7 +232,9 @@ async def test_user_host_already_configured( async def test_user_name_already_configured( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, ) -> None: """Test name is already configured during user setup.""" entry = MockConfigEntry( @@ -247,13 +246,7 @@ async def test_user_name_already_configured( fail_entry[CONF_HOST] = "0.0.0.0" result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": SOURCE_USER} - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - assert result["step_id"] == "user" - - result = await hass.config_entries.flow.async_configure( - result["flow_id"], fail_entry + DOMAIN, context={"source": SOURCE_USER}, data=fail_entry ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM @@ -261,7 +254,9 @@ async def test_user_name_already_configured( async def test_user_esn_already_exists( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup + 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 @@ -283,36 +278,25 @@ async def test_user_esn_already_exists( async def test_user_error_on_could_not_connect( - hass: HomeAssistantType, vizio_cant_connect + hass: HomeAssistantType, vizio_cant_connect: pytest.fixture ) -> None: """Test with could_not_connect during user_setup.""" result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": SOURCE_USER} + DOMAIN, context={"source": SOURCE_USER}, data=MOCK_USER_VALID_TV_CONFIG ) - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - assert result["step_id"] == "user" - - result = await hass.config_entries.flow.async_configure( - result["flow_id"], MOCK_USER_VALID_TV_CONFIG - ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM assert result["errors"] == {"base": "cant_connect"} async def test_user_error_on_tv_needs_token( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, ) -> None: """Test when config fails custom validation for non null access token when device_class = tv during user setup.""" result = await hass.config_entries.flow.async_init( - DOMAIN, context={"source": SOURCE_USER} - ) - - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM - assert result["step_id"] == "user" - - result = await hass.config_entries.flow.async_configure( - result["flow_id"], MOCK_INVALID_TV_CONFIG + DOMAIN, context={"source": SOURCE_USER}, data=MOCK_INVALID_TV_CONFIG ) assert result["type"] == data_entry_flow.RESULT_TYPE_FORM @@ -320,12 +304,14 @@ async def test_user_error_on_tv_needs_token( async def test_import_flow_minimum_fields( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, ) -> None: """Test import config flow with minimum fields.""" result = await hass.config_entries.flow.async_init( DOMAIN, - context={"source": "import"}, + context={"source": SOURCE_IMPORT}, data=vol.Schema(VIZIO_SCHEMA)( {CONF_HOST: HOST, CONF_DEVICE_CLASS: DEVICE_CLASS_SPEAKER} ), @@ -340,12 +326,14 @@ async def test_import_flow_minimum_fields( async def test_import_flow_all_fields( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, ) -> None: """Test import config flow with all fields.""" result = await hass.config_entries.flow.async_init( DOMAIN, - context={"source": "import"}, + context={"source": SOURCE_IMPORT}, data=vol.Schema(VIZIO_SCHEMA)(MOCK_IMPORT_VALID_TV_CONFIG), ) @@ -359,7 +347,9 @@ async def test_import_flow_all_fields( async def test_import_entity_already_configured( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, ) -> None: """Test entity is already configured during import setup.""" entry = MockConfigEntry( @@ -371,7 +361,7 @@ async def test_import_entity_already_configured( 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 + DOMAIN, context={"source": SOURCE_IMPORT}, data=fail_entry ) assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT @@ -379,7 +369,9 @@ async def test_import_entity_already_configured( async def test_import_flow_update_options( - hass: HomeAssistantType, vizio_connect, vizio_bypass_update + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_update: pytest.fixture, ) -> None: """Test import config flow with updated options.""" result = await hass.config_entries.flow.async_init( @@ -388,6 +380,7 @@ async def test_import_flow_update_options( data=vol.Schema(VIZIO_SCHEMA)(MOCK_IMPORT_VALID_TV_CONFIG), ) await hass.async_block_till_done() + assert result["result"].options == {CONF_VOLUME_STEP: VOLUME_STEP} assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY entry_id = result["result"].entry_id @@ -409,7 +402,10 @@ async def test_import_flow_update_options( async def test_zeroconf_flow( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup, vizio_guess_device_type + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, + vizio_guess_device_type: pytest.fixture, ) -> None: """Test zeroconf config flow.""" discovery_info = MOCK_ZEROCONF_ENTRY.copy() @@ -437,7 +433,9 @@ async def test_zeroconf_flow( async def test_zeroconf_flow_already_configured( - hass: HomeAssistantType, vizio_connect, vizio_bypass_setup + hass: HomeAssistantType, + vizio_connect: pytest.fixture, + vizio_bypass_setup: pytest.fixture, ) -> None: """Test entity is already configured during zeroconf setup.""" entry = MockConfigEntry(