"""Test Axis device.""" from unittest.mock import Mock, patch import pytest from tests.common import mock_coro, MockConfigEntry from homeassistant.components.axis import device, errors from homeassistant.components.axis.camera import AxisCamera DEVICE_DATA = { device.CONF_HOST: '1.2.3.4', device.CONF_USERNAME: 'username', device.CONF_PASSWORD: 'password', device.CONF_PORT: 1234 } ENTRY_OPTIONS = { device.CONF_CAMERA: True, device.CONF_EVENTS: True, } ENTRY_CONFIG = { device.CONF_DEVICE: DEVICE_DATA, device.CONF_MAC: 'mac', device.CONF_MODEL: 'model', device.CONF_NAME: 'name' } async def test_device_setup(): """Successful setup.""" hass = Mock() entry = Mock() entry.data = ENTRY_CONFIG entry.options = ENTRY_OPTIONS api = Mock() axis_device = device.AxisNetworkDevice(hass, entry) axis_device.start = Mock() assert axis_device.host == DEVICE_DATA[device.CONF_HOST] assert axis_device.model == ENTRY_CONFIG[device.CONF_MODEL] assert axis_device.name == ENTRY_CONFIG[device.CONF_NAME] assert axis_device.serial == ENTRY_CONFIG[device.CONF_MAC] with patch.object(device, 'get_device', return_value=mock_coro(api)): assert await axis_device.async_setup() is True assert axis_device.api is api assert len(hass.config_entries.async_forward_entry_setup.mock_calls) == 3 assert hass.config_entries.async_forward_entry_setup.mock_calls[0][1] == \ (entry, 'camera') assert hass.config_entries.async_forward_entry_setup.mock_calls[1][1] == \ (entry, 'binary_sensor') assert hass.config_entries.async_forward_entry_setup.mock_calls[2][1] == \ (entry, 'switch') async def test_device_signal_new_address(hass): """Successful setup.""" entry = MockConfigEntry( domain=device.DOMAIN, data=ENTRY_CONFIG, options=ENTRY_OPTIONS) api = Mock() api.vapix.get_param.return_value = '1234' axis_device = device.AxisNetworkDevice(hass, entry) hass.data[device.DOMAIN] = {axis_device.serial: axis_device} with patch.object(device, 'get_device', return_value=mock_coro(api)), \ patch.object(AxisCamera, '_new_address') as new_address_mock: await axis_device.async_setup() await hass.async_block_till_done() assert len(hass.states.async_all()) == 1 assert len(axis_device.listeners) == 2 entry.data[device.CONF_DEVICE][device.CONF_HOST] = '2.3.4.5' hass.config_entries.async_update_entry(entry, data=entry.data) await hass.async_block_till_done() assert axis_device.host == '2.3.4.5' assert axis_device.api.config.host == '2.3.4.5' assert len(new_address_mock.mock_calls) == 1 async def test_device_unavailable(hass): """Successful setup.""" entry = MockConfigEntry( domain=device.DOMAIN, data=ENTRY_CONFIG, options=ENTRY_OPTIONS) api = Mock() api.vapix.get_param.return_value = '1234' axis_device = device.AxisNetworkDevice(hass, entry) hass.data[device.DOMAIN] = {axis_device.serial: axis_device} with patch.object(device, 'get_device', return_value=mock_coro(api)), \ patch.object(device, 'async_dispatcher_send') as mock_dispatcher: await axis_device.async_setup() await hass.async_block_till_done() axis_device.async_connection_status_callback(status=False) assert not axis_device.available assert len(mock_dispatcher.mock_calls) == 1 async def test_device_reset(hass): """Successfully reset device.""" entry = MockConfigEntry( domain=device.DOMAIN, data=ENTRY_CONFIG, options=ENTRY_OPTIONS) api = Mock() api.vapix.get_param.return_value = '1234' axis_device = device.AxisNetworkDevice(hass, entry) hass.data[device.DOMAIN] = {axis_device.serial: axis_device} with patch.object(device, 'get_device', return_value=mock_coro(api)): await axis_device.async_setup() await hass.async_block_till_done() await axis_device.async_reset() assert len(api.stop.mock_calls) == 1 assert len(hass.states.async_all()) == 0 assert len(axis_device.listeners) == 0 async def test_device_not_accessible(): """Failed setup schedules a retry of setup.""" hass = Mock() hass.data = dict() entry = Mock() entry.data = ENTRY_CONFIG entry.options = ENTRY_OPTIONS axis_device = device.AxisNetworkDevice(hass, entry) with patch.object(device, 'get_device', side_effect=errors.CannotConnect), \ pytest.raises(device.ConfigEntryNotReady): await axis_device.async_setup() assert not hass.helpers.event.async_call_later.mock_calls async def test_device_unknown_error(): """Unknown errors are handled.""" hass = Mock() entry = Mock() entry.data = ENTRY_CONFIG entry.options = ENTRY_OPTIONS axis_device = device.AxisNetworkDevice(hass, entry) with patch.object(device, 'get_device', side_effect=Exception): assert await axis_device.async_setup() is False assert not hass.helpers.event.async_call_later.mock_calls async def test_new_event_sends_signal(hass): """Make sure that new event send signal.""" entry = Mock() entry.data = ENTRY_CONFIG axis_device = device.AxisNetworkDevice(hass, entry) with patch.object(device, 'async_dispatcher_send') as mock_dispatch_send: axis_device.async_event_callback(action='add', event_id='event') await hass.async_block_till_done() assert len(mock_dispatch_send.mock_calls) == 1 assert len(mock_dispatch_send.mock_calls[0]) == 3 async def test_shutdown(): """Successful shutdown.""" hass = Mock() entry = Mock() entry.data = ENTRY_CONFIG axis_device = device.AxisNetworkDevice(hass, entry) axis_device.api = Mock() axis_device.shutdown(None) assert len(axis_device.api.stop.mock_calls) == 1 async def test_get_device(hass): """Successful call.""" with patch('axis.param_cgi.Params.update_brand', return_value=mock_coro()), \ patch('axis.param_cgi.Params.update_properties', return_value=mock_coro()), \ patch('axis.port_cgi.Ports.update', return_value=mock_coro()): assert await device.get_device(hass, DEVICE_DATA) async def test_get_device_fails(hass): """Device unauthorized yields authentication required error.""" import axis with patch('axis.param_cgi.Params.update_brand', side_effect=axis.Unauthorized), \ pytest.raises(errors.AuthenticationRequired): await device.get_device(hass, DEVICE_DATA) async def test_get_device_device_unavailable(hass): """Device unavailable yields cannot connect error.""" import axis with patch('axis.param_cgi.Params.update_brand', side_effect=axis.RequestError), \ pytest.raises(errors.CannotConnect): await device.get_device(hass, DEVICE_DATA) async def test_get_device_unknown_error(hass): """Device yield unknown error.""" import axis with patch('axis.param_cgi.Params.update_brand', side_effect=axis.AxisException), \ pytest.raises(errors.AuthenticationRequired): await device.get_device(hass, DEVICE_DATA)