"""Tests for the GogoGate2 component.""" from datetime import timedelta from gogogate2_api import GogoGate2Api, ISmartGateApi from gogogate2_api.common import ( ApiError, DoorMode, DoorStatus, GogoGate2ActivateResponse, GogoGate2Door, GogoGate2InfoResponse, ISmartGateDoor, ISmartGateInfoResponse, Network, Outputs, Wifi, ) from homeassistant.components.cover import ( DEVICE_CLASS_GARAGE, DEVICE_CLASS_GATE, DOMAIN as COVER_DOMAIN, ) from homeassistant.components.gogogate2.const import ( DEVICE_TYPE_GOGOGATE2, DEVICE_TYPE_ISMARTGATE, DOMAIN, MANUFACTURER, ) from homeassistant.components.homeassistant import DOMAIN as HA_DOMAIN from homeassistant.config import async_process_ha_core_config from homeassistant.config_entries import SOURCE_USER from homeassistant.const import ( ATTR_DEVICE_CLASS, CONF_DEVICE, CONF_IP_ADDRESS, CONF_NAME, CONF_PASSWORD, CONF_PLATFORM, CONF_UNIT_SYSTEM, CONF_UNIT_SYSTEM_METRIC, CONF_USERNAME, STATE_CLOSED, STATE_OPEN, STATE_UNAVAILABLE, STATE_UNKNOWN, ) from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component from homeassistant.util.dt import utcnow from tests.async_mock import MagicMock, patch from tests.common import MockConfigEntry, async_fire_time_changed, mock_device_registry def _mocked_gogogate_open_door_response(): return GogoGate2InfoResponse( user="user1", gogogatename="gogogatename0", model="gogogate2", apiversion="", remoteaccessenabled=False, remoteaccess="abc123.blah.blah", firmwareversion="222", apicode="", door1=GogoGate2Door( door_id=1, permission=True, name="Door1", gate=False, mode=DoorMode.GARAGE, status=DoorStatus.OPENED, sensor=True, sensorid=None, camera=False, events=2, temperature=None, voltage=40, ), door2=GogoGate2Door( door_id=2, permission=True, name=None, gate=True, mode=DoorMode.GARAGE, status=DoorStatus.UNDEFINED, sensor=True, sensorid=None, camera=False, events=0, temperature=None, voltage=40, ), door3=GogoGate2Door( door_id=3, permission=True, name=None, gate=False, mode=DoorMode.GARAGE, status=DoorStatus.UNDEFINED, sensor=True, sensorid=None, camera=False, events=0, temperature=None, voltage=40, ), outputs=Outputs(output1=True, output2=False, output3=True), network=Network(ip=""), wifi=Wifi(SSID="", linkquality="", signal=""), ) def _mocked_ismartgate_closed_door_response(): return ISmartGateInfoResponse( user="user1", ismartgatename="ismartgatename0", model="ismartgatePRO", apiversion="", remoteaccessenabled=False, remoteaccess="abc321.blah.blah", firmwareversion="555", pin=123, lang="en", newfirmware=False, door1=ISmartGateDoor( door_id=1, permission=True, name="Door1", gate=False, mode=DoorMode.GARAGE, status=DoorStatus.CLOSED, sensor=True, sensorid=None, camera=False, events=2, temperature=None, enabled=True, apicode="apicode0", customimage=False, voltage=40, ), door2=ISmartGateDoor( door_id=2, permission=True, name="Door2", gate=True, mode=DoorMode.GARAGE, status=DoorStatus.CLOSED, sensor=True, sensorid=None, camera=False, events=2, temperature=None, enabled=True, apicode="apicode0", customimage=False, voltage=40, ), door3=ISmartGateDoor( door_id=3, permission=True, name=None, gate=False, mode=DoorMode.GARAGE, status=DoorStatus.UNDEFINED, sensor=True, sensorid=None, camera=False, events=0, temperature=None, enabled=True, apicode="apicode0", customimage=False, voltage=40, ), network=Network(ip=""), wifi=Wifi(SSID="", linkquality="", signal=""), ) @patch("homeassistant.components.gogogate2.common.GogoGate2Api") async def test_import_fail(gogogate2api_mock, hass: HomeAssistant) -> None: """Test the failure to import.""" api = MagicMock(spec=GogoGate2Api) api.info.side_effect = ApiError(22, "Error") gogogate2api_mock.return_value = api hass_config = { HA_DOMAIN: {CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC}, COVER_DOMAIN: [ { CONF_PLATFORM: "gogogate2", CONF_NAME: "cover0", CONF_DEVICE: DEVICE_TYPE_GOGOGATE2, CONF_IP_ADDRESS: "127.0.1.0", CONF_USERNAME: "user0", CONF_PASSWORD: "password0", } ], } await async_process_ha_core_config(hass, hass_config[HA_DOMAIN]) assert await async_setup_component(hass, HA_DOMAIN, {}) assert await async_setup_component(hass, COVER_DOMAIN, hass_config) await hass.async_block_till_done() entity_ids = hass.states.async_entity_ids(COVER_DOMAIN) assert not entity_ids @patch("homeassistant.components.gogogate2.common.GogoGate2Api") @patch("homeassistant.components.gogogate2.common.ISmartGateApi") async def test_import( ismartgateapi_mock, gogogate2api_mock, hass: HomeAssistant ) -> None: """Test importing of file based config.""" api0 = MagicMock(spec=GogoGate2Api) api0.info.return_value = _mocked_gogogate_open_door_response() gogogate2api_mock.return_value = api0 api1 = MagicMock(spec=ISmartGateApi) api1.info.return_value = _mocked_ismartgate_closed_door_response() ismartgateapi_mock.return_value = api1 hass_config = { HA_DOMAIN: {CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC}, COVER_DOMAIN: [ { CONF_PLATFORM: "gogogate2", CONF_NAME: "cover0", CONF_DEVICE: DEVICE_TYPE_GOGOGATE2, CONF_IP_ADDRESS: "127.0.1.0", CONF_USERNAME: "user0", CONF_PASSWORD: "password0", }, { CONF_PLATFORM: "gogogate2", CONF_NAME: "cover1", CONF_DEVICE: DEVICE_TYPE_ISMARTGATE, CONF_IP_ADDRESS: "127.0.1.1", CONF_USERNAME: "user1", CONF_PASSWORD: "password1", }, ], } await async_process_ha_core_config(hass, hass_config[HA_DOMAIN]) assert await async_setup_component(hass, HA_DOMAIN, {}) assert await async_setup_component(hass, COVER_DOMAIN, hass_config) await hass.async_block_till_done() entity_ids = hass.states.async_entity_ids(COVER_DOMAIN) assert entity_ids is not None assert len(entity_ids) == 3 assert "cover.door1" in entity_ids assert "cover.door1_2" in entity_ids assert "cover.door2" in entity_ids @patch("homeassistant.components.gogogate2.common.GogoGate2Api") async def test_open_close_update(gogogate2api_mock, hass: HomeAssistant) -> None: """Test open and close and data update.""" def info_response(door_status: DoorStatus) -> GogoGate2InfoResponse: return GogoGate2InfoResponse( user="user1", gogogatename="gogogatename0", model="", apiversion="", remoteaccessenabled=False, remoteaccess="abc123.blah.blah", firmwareversion="", apicode="", door1=GogoGate2Door( door_id=1, permission=True, name="Door1", gate=False, mode=DoorMode.GARAGE, status=door_status, sensor=True, sensorid=None, camera=False, events=2, temperature=None, voltage=40, ), door2=GogoGate2Door( door_id=2, permission=True, name=None, gate=True, mode=DoorMode.GARAGE, status=DoorStatus.UNDEFINED, sensor=True, sensorid=None, camera=False, events=0, temperature=None, voltage=40, ), door3=GogoGate2Door( door_id=3, permission=True, name=None, gate=False, mode=DoorMode.GARAGE, status=DoorStatus.UNDEFINED, sensor=True, sensorid=None, camera=False, events=0, temperature=None, voltage=40, ), outputs=Outputs(output1=True, output2=False, output3=True), network=Network(ip=""), wifi=Wifi(SSID="", linkquality="", signal=""), ) api = MagicMock(GogoGate2Api) api.activate.return_value = GogoGate2ActivateResponse(result=True) api.info.return_value = info_response(DoorStatus.OPENED) gogogate2api_mock.return_value = api config_entry = MockConfigEntry( domain=DOMAIN, source=SOURCE_USER, data={ CONF_IP_ADDRESS: "127.0.0.1", CONF_USERNAME: "admin", CONF_PASSWORD: "password", }, ) config_entry.add_to_hass(hass) assert hass.states.get("cover.door1") is None assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_OPEN api.info.return_value = info_response(DoorStatus.CLOSED) await hass.services.async_call( COVER_DOMAIN, "close_cover", service_data={"entity_id": "cover.door1"}, ) async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_CLOSED api.close_door.assert_called_with(1) api.info.return_value = info_response(DoorStatus.OPENED) await hass.services.async_call( COVER_DOMAIN, "open_cover", service_data={"entity_id": "cover.door1"}, ) async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_OPEN api.open_door.assert_called_with(1) api.info.return_value = info_response(DoorStatus.UNDEFINED) async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_UNKNOWN assert await hass.config_entries.async_unload(config_entry.entry_id) assert not hass.states.async_entity_ids(DOMAIN) @patch("homeassistant.components.gogogate2.common.ISmartGateApi") async def test_availability(ismartgateapi_mock, hass: HomeAssistant) -> None: """Test availability.""" closed_door_response = _mocked_ismartgate_closed_door_response() api = MagicMock(ISmartGateApi) api.info.return_value = closed_door_response ismartgateapi_mock.return_value = api config_entry = MockConfigEntry( domain=DOMAIN, source=SOURCE_USER, data={ CONF_DEVICE: DEVICE_TYPE_ISMARTGATE, CONF_IP_ADDRESS: "127.0.0.1", CONF_USERNAME: "admin", CONF_PASSWORD: "password", }, ) config_entry.add_to_hass(hass) assert hass.states.get("cover.door1") is None assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert hass.states.get("cover.door1") assert ( hass.states.get("cover.door1").attributes[ATTR_DEVICE_CLASS] == DEVICE_CLASS_GARAGE ) assert ( hass.states.get("cover.door2").attributes[ATTR_DEVICE_CLASS] == DEVICE_CLASS_GATE ) api.info.side_effect = Exception("Error") async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_UNAVAILABLE api.info.side_effect = None api.info.return_value = closed_door_response async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("cover.door1").state == STATE_CLOSED @patch("homeassistant.components.gogogate2.common.ISmartGateApi") async def test_device_info_ismartgate(ismartgateapi_mock, hass: HomeAssistant) -> None: """Test device info.""" device_registry = mock_device_registry(hass) closed_door_response = _mocked_ismartgate_closed_door_response() api = MagicMock(ISmartGateApi) api.info.return_value = closed_door_response ismartgateapi_mock.return_value = api config_entry = MockConfigEntry( domain=DOMAIN, source=SOURCE_USER, title="mycontroller", unique_id="xyz", data={ CONF_DEVICE: DEVICE_TYPE_ISMARTGATE, CONF_IP_ADDRESS: "127.0.0.1", CONF_USERNAME: "admin", CONF_PASSWORD: "password", }, ) config_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() device = device_registry.async_get_device({(DOMAIN, "xyz")}, set()) assert device assert device.manufacturer == MANUFACTURER assert device.name == "mycontroller" assert device.model == "ismartgatePRO" assert device.sw_version == "555" @patch("homeassistant.components.gogogate2.common.GogoGate2Api") async def test_device_info_gogogate2(gogogate2api_mock, hass: HomeAssistant) -> None: """Test device info.""" device_registry = mock_device_registry(hass) closed_door_response = _mocked_gogogate_open_door_response() api = MagicMock(GogoGate2Api) api.info.return_value = closed_door_response gogogate2api_mock.return_value = api config_entry = MockConfigEntry( domain=DOMAIN, source=SOURCE_USER, title="mycontroller", unique_id="xyz", data={ CONF_DEVICE: DEVICE_TYPE_GOGOGATE2, CONF_IP_ADDRESS: "127.0.0.1", CONF_USERNAME: "admin", CONF_PASSWORD: "password", }, ) config_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() device = device_registry.async_get_device({(DOMAIN, "xyz")}, set()) assert device assert device.manufacturer == MANUFACTURER assert device.name == "mycontroller" assert device.model == "gogogate2" assert device.sw_version == "222"