"""Tests for the GogoGate2 component.""" from datetime import timedelta from unittest.mock import MagicMock, patch from ismartgate import GogoGate2Api, ISmartGateApi from ismartgate.common import ( DoorMode, DoorStatus, GogoGate2ActivateResponse, GogoGate2Door, GogoGate2InfoResponse, ISmartGateDoor, ISmartGateInfoResponse, Network, Outputs, Wifi, ) from homeassistant.components.gogogate2.const import DEVICE_TYPE_ISMARTGATE, DOMAIN from homeassistant.components.sensor import SensorDeviceClass from homeassistant.config_entries import SOURCE_USER from homeassistant.const import ( ATTR_DEVICE_CLASS, ATTR_UNIT_OF_MEASUREMENT, CONF_DEVICE, CONF_IP_ADDRESS, CONF_PASSWORD, CONF_USERNAME, STATE_UNAVAILABLE, STATE_UNKNOWN, ) from homeassistant.core import HomeAssistant from homeassistant.util.dt import utcnow from tests.common import MockConfigEntry, async_fire_time_changed def _mocked_gogogate_sensor_response(battery_level: int, temperature: float): 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=DoorStatus.OPENED, sensor=True, sensorid="ABCD", camera=False, events=2, temperature=temperature, voltage=battery_level, ), door2=GogoGate2Door( door_id=2, permission=True, name="Door2", gate=True, mode=DoorMode.GARAGE, status=DoorStatus.UNDEFINED, sensor=True, sensorid="WIRE", camera=False, events=0, temperature=temperature, voltage=battery_level, ), door3=GogoGate2Door( door_id=3, permission=True, name="Door3", gate=False, mode=DoorMode.GARAGE, status=DoorStatus.UNDEFINED, sensor=True, sensorid=None, camera=False, events=0, temperature=temperature, voltage=battery_level, ), outputs=Outputs(output1=True, output2=False, output3=True), network=Network(ip=""), wifi=Wifi(SSID="", linkquality="", signal=""), ) def _mocked_ismartgate_sensor_response(battery_level: int, temperature: float): 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="ABCD", camera=False, events=2, temperature=temperature, enabled=True, apicode="apicode0", customimage=False, voltage=battery_level, ), door2=ISmartGateDoor( door_id=2, permission=True, name="Door2", gate=True, mode=DoorMode.GARAGE, status=DoorStatus.CLOSED, sensor=True, sensorid="WIRE", camera=False, events=2, temperature=temperature, enabled=True, apicode="apicode0", customimage=False, voltage=battery_level, ), door3=ISmartGateDoor( door_id=3, permission=True, name="Door3", gate=False, mode=DoorMode.GARAGE, status=DoorStatus.UNDEFINED, sensor=True, sensorid=None, camera=False, events=0, temperature=temperature, enabled=True, apicode="apicode0", customimage=False, voltage=battery_level, ), network=Network(ip=""), wifi=Wifi(SSID="", linkquality="", signal=""), ) @patch("homeassistant.components.gogogate2.common.GogoGate2Api") async def test_sensor_update(gogogate2api_mock, hass: HomeAssistant) -> None: """Test data update.""" bat_attributes = { "device_class": "battery", "door_id": 1, "friendly_name": "Door1 battery", "sensor_id": "ABCD", "state_class": "measurement", "unit_of_measurement": "%", } temp_attributes = { "device_class": "temperature", "door_id": 1, "friendly_name": "Door1 temperature", "sensor_id": "ABCD", "unit_of_measurement": "°C", "state_class": "measurement", } api = MagicMock(GogoGate2Api) api.async_activate.return_value = GogoGate2ActivateResponse(result=True) api.async_info.return_value = _mocked_gogogate_sensor_response(25, 7.0) 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 hass.states.get("cover.door2") is None assert hass.states.get("cover.door3") is None assert hass.states.get("sensor.door1_battery") is None assert hass.states.get("sensor.door2_battery") is None assert hass.states.get("sensor.door3_battery") is None assert hass.states.get("sensor.door1_temperature") is None assert hass.states.get("sensor.door2_temperature") is None assert hass.states.get("sensor.door3_temperature") 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.door2") assert hass.states.get("cover.door3") assert hass.states.get("sensor.door1_battery").state == "25" assert dict(hass.states.get("sensor.door1_battery").attributes) == bat_attributes assert hass.states.get("sensor.door2_battery") is None assert hass.states.get("sensor.door2_battery") is None assert hass.states.get("sensor.door1_temperature").state == "7.0" assert ( dict(hass.states.get("sensor.door1_temperature").attributes) == temp_attributes ) assert hass.states.get("sensor.door2_temperature") is None assert hass.states.get("sensor.door3_temperature") is None api.async_info.return_value = _mocked_gogogate_sensor_response(40, 10.0) async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("sensor.door1_battery").state == "40" assert hass.states.get("sensor.door1_temperature").state == "10.0" api.async_info.return_value = _mocked_gogogate_sensor_response(None, None) async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("sensor.door1_battery").state == STATE_UNKNOWN assert hass.states.get("sensor.door1_temperature").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.""" bat_attributes = { "device_class": "battery", "door_id": 1, "friendly_name": "Door1 battery", "sensor_id": "ABCD", "state_class": "measurement", "unit_of_measurement": "%", } temp_attributes = { "device_class": "temperature", "door_id": 1, "friendly_name": "Door1 temperature", "sensor_id": "ABCD", "unit_of_measurement": "°C", "state_class": "measurement", } sensor_response = _mocked_ismartgate_sensor_response(35, -4.0) api = MagicMock(ISmartGateApi) api.async_info.return_value = sensor_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 hass.states.get("cover.door2") is None assert hass.states.get("cover.door3") is None assert hass.states.get("sensor.door1_battery") is None assert hass.states.get("sensor.door2_battery") is None assert hass.states.get("sensor.door3_battery") 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.door2") assert hass.states.get("cover.door3") assert hass.states.get("sensor.door1_battery").state == "35" assert hass.states.get("sensor.door2_battery") is None assert hass.states.get("sensor.door3_battery") is None assert hass.states.get("sensor.door1_temperature").state == "-4.0" assert hass.states.get("sensor.door2_temperature") is None assert hass.states.get("sensor.door3_temperature") is None assert ( hass.states.get("sensor.door1_battery").attributes[ATTR_DEVICE_CLASS] == SensorDeviceClass.BATTERY ) assert ( hass.states.get("sensor.door1_temperature").attributes[ATTR_DEVICE_CLASS] == SensorDeviceClass.TEMPERATURE ) assert ( hass.states.get("sensor.door1_temperature").attributes[ATTR_UNIT_OF_MEASUREMENT] == "°C" ) api.async_info.side_effect = Exception("Error") async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("sensor.door1_battery").state == STATE_UNAVAILABLE assert hass.states.get("sensor.door1_temperature").state == STATE_UNAVAILABLE api.async_info.side_effect = None api.async_info.return_value = sensor_response async_fire_time_changed(hass, utcnow() + timedelta(hours=2)) await hass.async_block_till_done() assert hass.states.get("sensor.door1_battery").state == "35" assert dict(hass.states.get("sensor.door1_battery").attributes) == bat_attributes assert ( dict(hass.states.get("sensor.door1_temperature").attributes) == temp_attributes )