async def test_flow_reauth_invalid_host(hass): """Test we do not accept an invalid host for reauthentication. The MAC address cannot change. """ device = get_device("Living Room") mock_entry = device.get_mock_entry() mock_entry.add_to_hass(hass) mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() data = {"name": device.name, **device.get_entry_data()} with patch("broadlink.gendevice", return_value=mock_api): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": "reauth"}, data=data) device.mac = get_device("Office").mac mock_api = device.get_mock_api() with patch("broadlink.discover", return_value=[mock_api]) as mock_discover: result = await hass.config_entries.flow.async_configure( result["flow_id"], { "host": device.host, "timeout": device.timeout }, ) assert result["type"] == "form" assert result["step_id"] == "user" assert result["errors"] == {"base": "invalid_host"} assert mock_discover.call_count == 1 assert mock_api.auth.call_count == 0
async def test_flow_reauth_valid_host(hass): """Test we accept a valid host for reauthentication. The hostname/IP address may change. We need to update the entry. """ device = get_device("Living Room") mock_entry = device.get_mock_entry() mock_entry.add_to_hass(hass) mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() data = {"name": device.name, **device.get_entry_data()} with patch("broadlink.gendevice", return_value=mock_api): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": "reauth"}, data=data) device.host = "192.168.1.128" mock_api = device.get_mock_api() with patch("broadlink.discover", return_value=[mock_api]) as mock_discover: result = await hass.config_entries.flow.async_configure( result["flow_id"], { "host": device.host, "timeout": device.timeout }, ) assert result["type"] == "abort" assert result["reason"] == "already_configured" assert mock_entry.data["host"] == device.host assert mock_discover.call_count == 1 assert mock_api.auth.call_count == 1
async def test_flow_reset_works(hass): """Test we finish a config flow after a factory reset.""" device = get_device("Living Room") mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER}) with patch("broadlink.discover", return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], { "host": device.host, "timeout": device.timeout }, ) with patch("broadlink.discover", return_value=[device.get_mock_api()]): result = await hass.config_entries.flow.async_configure( result["flow_id"], { "host": device.host, "timeout": device.timeout }, ) result = await hass.config_entries.flow.async_configure( result["flow_id"], {"name": device.name}, ) assert result["type"] == "create_entry" assert result["title"] == device.name assert result["data"] == device.get_entry_data()
async def test_flow_reauth_works(hass): """Test a reauthentication flow.""" device = get_device("Living Room") mock_entry = device.get_mock_entry() mock_entry.add_to_hass(hass) mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() data = {"name": device.name, **device.get_entry_data()} with patch("broadlink.gendevice", return_value=mock_api): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": "reauth"}, data=data) assert result["type"] == "form" assert result["step_id"] == "reset" mock_api = device.get_mock_api() with patch("broadlink.discover", return_value=[mock_api]) as mock_discover: result = await hass.config_entries.flow.async_configure( result["flow_id"], { "host": device.host, "timeout": device.timeout }, ) assert result["type"] == "abort" assert result["reason"] == "already_configured" assert dict(mock_entry.data) == device.get_entry_data() assert mock_api.auth.call_count == 1 assert mock_discover.call_count == 1
async def test_flow_reauth_valid_host(opp): """Test we accept a valid host for reauthentication. The hostname/IP address may change. We need to update the entry. """ device = get_device("Living Room") mock_entry = device.get_mock_entry() mock_entry.add_to_opp(opp) mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() data = {"name": device.name, **device.get_entry_data()} with patch(DEVICE_FACTORY, return_value=mock_api): result = await opp.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_REAUTH}, data=data ) device.host = "192.168.1.128" mock_api = device.get_mock_api() with patch(DEVICE_HELLO, return_value=mock_api) as mock_hello: result = await opp.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, ) assert result["type"] == "abort" assert result["reason"] == "already_configured" assert mock_entry.data["host"] == device.host assert mock_hello.call_count == 1 assert mock_api.auth.call_count == 1
async def test_device_setup_update_authentication_error(hass): """Test we handle an authentication error in the update step.""" device = get_device("Living Room") mock_api = device.get_mock_api() mock_api.check_sensors.side_effect = blke.AuthorizationError() mock_api.auth.side_effect = (None, blke.AuthenticationError()) mock_entry = device.get_mock_entry() mock_entry.add_to_hass(hass) with patch("broadlink.gendevice", return_value=mock_api), patch.object( hass.config_entries, "async_forward_entry_setup" ) as mock_forward, patch.object( hass.config_entries.flow, "async_init" ) as mock_init: await hass.config_entries.async_setup(mock_entry.entry_id) assert mock_entry.state == ENTRY_STATE_SETUP_RETRY assert mock_api.auth.call_count == 2 assert mock_api.check_sensors.call_count == 1 assert mock_forward.call_count == 0 assert mock_init.call_count == 1 assert mock_init.mock_calls[0][2]["context"]["source"] == "reauth" assert mock_init.mock_calls[0][2]["data"] == { "name": device.name, **device.get_entry_data(), }
async def test_flow_reauth_invalid_host(opp): """Test we do not accept an invalid host for reauthentication. The MAC address cannot change. """ device = get_device("Living Room") mock_entry = device.get_mock_entry() mock_entry.add_to_opp(opp) mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() data = {"name": device.name, **device.get_entry_data()} with patch(DEVICE_FACTORY, return_value=mock_api): result = await opp.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_REAUTH}, data=data ) device.mac = get_device("Office").mac mock_api = device.get_mock_api() with patch(DEVICE_HELLO, return_value=mock_api) as mock_hello: result = await opp.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, ) assert result["type"] == "form" assert result["step_id"] == "user" assert result["errors"] == {"base": "invalid_host"} assert mock_hello.call_count == 1 assert mock_api.auth.call_count == 0
async def test_flow_reauth_works(opp): """Test a reauthentication flow.""" device = get_device("Living Room") mock_entry = device.get_mock_entry() mock_entry.add_to_opp(opp) mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() data = {"name": device.name, **device.get_entry_data()} with patch(DEVICE_FACTORY, return_value=mock_api): result = await opp.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_REAUTH}, data=data ) assert result["type"] == "form" assert result["step_id"] == "reset" mock_api = device.get_mock_api() with patch(DEVICE_HELLO, return_value=mock_api) as mock_hello: result = await opp.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, ) assert result["type"] == "abort" assert result["reason"] == "already_configured" assert dict(mock_entry.data) == device.get_entry_data() assert mock_api.auth.call_count == 1 assert mock_hello.call_count == 1
async def test_flow_reset_works(opp): """Test we finish a config flow after a manual unlock.""" device = get_device("Living Room") mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() result = await opp.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) with patch(DEVICE_HELLO, return_value=mock_api): result = await opp.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, ) with patch(DEVICE_HELLO, return_value=device.get_mock_api()): result = await opp.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, ) result = await opp.config_entries.flow.async_configure( result["flow_id"], {"name": device.name}, ) assert result["type"] == "create_entry" assert result["title"] == device.name assert result["data"] == device.get_entry_data()
async def test_device_unload_authentication_error(hass): """Test we unload a device that failed the authentication step.""" device = get_device("Living Room") mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() with patch.object(hass.config_entries, "async_forward_entry_setup"), patch.object( hass.config_entries.flow, "async_init"): _, mock_entry = await device.setup_entry(hass, mock_api=mock_api) with patch.object(hass.config_entries, "async_forward_entry_unload", return_value=True) as mock_forward: await hass.config_entries.async_unload(mock_entry.entry_id) assert mock_entry.state == ENTRY_STATE_NOT_LOADED assert mock_forward.call_count == 0
async def test_flow_auth_authentication_error(hass): """Test we handle an authentication error in the auth step.""" device = get_device("Living Room") mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) with patch(DEVICE_DISCOVERY, return_value=[mock_api]): result = await hass.config_entries.flow.async_configure( result["flow_id"], {"host": device.host, "timeout": device.timeout}, ) assert result["type"] == "form" assert result["step_id"] == "reset" assert result["errors"] == {"base": "invalid_auth"}
async def test_device_setup_authentication_error(opp): """Test we handle an authentication error.""" device = get_device("Living Room") mock_api = device.get_mock_api() mock_api.auth.side_effect = blke.AuthenticationError() with patch.object( opp.config_entries, "async_forward_entry_setup" ) as mock_forward, patch.object(opp.config_entries.flow, "async_init") as mock_init: mock_api, mock_entry = await device.setup_entry(opp, mock_api=mock_api) assert mock_entry.state == ConfigEntryState.SETUP_ERROR assert mock_api.auth.call_count == 1 assert mock_forward.call_count == 0 assert mock_init.call_count == 1 assert mock_init.mock_calls[0][2]["context"]["source"] == "reauth" assert mock_init.mock_calls[0][2]["data"] == { "name": device.name, **device.get_entry_data(), }
async def test_device_setup_update_authentication_error(opp): """Test we handle an authentication error in the update step.""" device = get_device("Garage") mock_api = device.get_mock_api() mock_api.check_sensors.side_effect = blke.AuthorizationError() mock_api.auth.side_effect = (None, blke.AuthenticationError()) with patch.object( opp.config_entries, "async_forward_entry_setup" ) as mock_forward, patch.object(opp.config_entries.flow, "async_init") as mock_init: mock_api, mock_entry = await device.setup_entry(opp, mock_api=mock_api) assert mock_entry.state is ConfigEntryState.SETUP_RETRY assert mock_api.auth.call_count == 2 assert mock_api.check_sensors.call_count == 1 assert mock_forward.call_count == 0 assert mock_init.call_count == 1 assert mock_init.mock_calls[0][2]["context"]["source"] == "reauth" assert mock_init.mock_calls[0][2]["data"] == { "name": device.name, **device.get_entry_data(), }