562 lines
19 KiB
Python
562 lines
19 KiB
Python
"""The tests for the DirecTV Media player platform."""
|
|
from unittest.mock import call, patch
|
|
|
|
from datetime import datetime, timedelta
|
|
import requests
|
|
import pytest
|
|
|
|
from homeassistant.components.media_player.const import (
|
|
ATTR_MEDIA_CONTENT_ID, ATTR_MEDIA_CONTENT_TYPE, MEDIA_TYPE_TVSHOW,
|
|
ATTR_MEDIA_ENQUEUE, ATTR_MEDIA_DURATION, ATTR_MEDIA_TITLE,
|
|
ATTR_MEDIA_POSITION, ATTR_MEDIA_SERIES_TITLE, ATTR_MEDIA_CHANNEL,
|
|
ATTR_INPUT_SOURCE, ATTR_MEDIA_POSITION_UPDATED_AT, DOMAIN,
|
|
SERVICE_PLAY_MEDIA, SUPPORT_PAUSE, SUPPORT_TURN_ON, SUPPORT_TURN_OFF,
|
|
SUPPORT_PLAY_MEDIA, SUPPORT_STOP, SUPPORT_NEXT_TRACK,
|
|
SUPPORT_PREVIOUS_TRACK, SUPPORT_PLAY)
|
|
from homeassistant.components.directv.media_player import (
|
|
ATTR_MEDIA_CURRENTLY_RECORDING, ATTR_MEDIA_RATING, ATTR_MEDIA_RECORDED,
|
|
ATTR_MEDIA_START_TIME, DEFAULT_DEVICE, DEFAULT_PORT)
|
|
from homeassistant.const import (
|
|
ATTR_ENTITY_ID, CONF_DEVICE, CONF_HOST, CONF_NAME, CONF_PORT,
|
|
SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY,
|
|
SERVICE_MEDIA_PREVIOUS_TRACK, SERVICE_MEDIA_STOP, SERVICE_TURN_OFF,
|
|
SERVICE_TURN_ON, STATE_OFF, STATE_PAUSED, STATE_PLAYING, STATE_UNAVAILABLE)
|
|
from homeassistant.helpers.discovery import async_load_platform
|
|
from homeassistant.setup import async_setup_component
|
|
import homeassistant.util.dt as dt_util
|
|
|
|
from tests.common import MockDependency, async_fire_time_changed
|
|
|
|
CLIENT_ENTITY_ID = 'media_player.client_dvr'
|
|
MAIN_ENTITY_ID = 'media_player.main_dvr'
|
|
IP_ADDRESS = '127.0.0.1'
|
|
|
|
DISCOVERY_INFO = {
|
|
'host': IP_ADDRESS,
|
|
'serial': 1234
|
|
}
|
|
|
|
LIVE = {
|
|
"callsign": "HASSTV",
|
|
"date": "20181110",
|
|
"duration": 3600,
|
|
"isOffAir": False,
|
|
"isPclocked": 1,
|
|
"isPpv": False,
|
|
"isRecording": False,
|
|
"isVod": False,
|
|
"major": 202,
|
|
"minor": 65535,
|
|
"offset": 1,
|
|
"programId": "102454523",
|
|
"rating": "No Rating",
|
|
"startTime": 1541876400,
|
|
"stationId": 3900947,
|
|
"title": "Using Home Assistant to automate your home"
|
|
}
|
|
|
|
LOCATIONS = [
|
|
{
|
|
'locationName': 'Main DVR',
|
|
'clientAddr': DEFAULT_DEVICE
|
|
}
|
|
]
|
|
|
|
RECORDING = {
|
|
"callsign": "HASSTV",
|
|
"date": "20181110",
|
|
"duration": 3600,
|
|
"isOffAir": False,
|
|
"isPclocked": 1,
|
|
"isPpv": False,
|
|
"isRecording": True,
|
|
"isVod": False,
|
|
"major": 202,
|
|
"minor": 65535,
|
|
"offset": 1,
|
|
"programId": "102454523",
|
|
"rating": "No Rating",
|
|
"startTime": 1541876400,
|
|
"stationId": 3900947,
|
|
"title": "Using Home Assistant to automate your home",
|
|
'uniqueId': '12345',
|
|
'episodeTitle': 'Configure DirecTV platform.'
|
|
}
|
|
|
|
WORKING_CONFIG = {
|
|
'media_player': {
|
|
'platform': 'directv',
|
|
CONF_HOST: IP_ADDRESS,
|
|
CONF_NAME: 'Main DVR',
|
|
CONF_PORT: DEFAULT_PORT,
|
|
CONF_DEVICE: DEFAULT_DEVICE
|
|
}
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def client_dtv():
|
|
"""Fixture for a client device."""
|
|
mocked_dtv = MockDirectvClass('mock_ip')
|
|
mocked_dtv.attributes = RECORDING
|
|
mocked_dtv._standby = False
|
|
return mocked_dtv
|
|
|
|
|
|
@pytest.fixture
|
|
def main_dtv():
|
|
"""Fixture for main DVR."""
|
|
return MockDirectvClass('mock_ip')
|
|
|
|
|
|
@pytest.fixture
|
|
def dtv_side_effect(client_dtv, main_dtv):
|
|
"""Fixture to create DIRECTV instance for main and client."""
|
|
def mock_dtv(ip, port, client_addr):
|
|
if client_addr != '0':
|
|
mocked_dtv = client_dtv
|
|
else:
|
|
mocked_dtv = main_dtv
|
|
mocked_dtv._host = ip
|
|
mocked_dtv._port = port
|
|
mocked_dtv._device = client_addr
|
|
return mocked_dtv
|
|
return mock_dtv
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_now():
|
|
"""Fixture for dtutil.now."""
|
|
return dt_util.utcnow()
|
|
|
|
|
|
@pytest.fixture
|
|
def platforms(hass, dtv_side_effect, mock_now):
|
|
"""Fixture for setting up test platforms."""
|
|
config = {
|
|
'media_player': [{
|
|
'platform': 'directv',
|
|
'name': 'Main DVR',
|
|
'host': IP_ADDRESS,
|
|
'port': DEFAULT_PORT,
|
|
'device': DEFAULT_DEVICE
|
|
}, {
|
|
'platform': 'directv',
|
|
'name': 'Client DVR',
|
|
'host': IP_ADDRESS,
|
|
'port': DEFAULT_PORT,
|
|
'device': '1'
|
|
}]
|
|
}
|
|
|
|
with MockDependency('DirectPy'), \
|
|
patch('DirectPy.DIRECTV', side_effect=dtv_side_effect), \
|
|
patch('homeassistant.util.dt.utcnow', return_value=mock_now):
|
|
hass.loop.run_until_complete(async_setup_component(
|
|
hass, DOMAIN, config))
|
|
hass.loop.run_until_complete(hass.async_block_till_done())
|
|
yield
|
|
|
|
|
|
async def async_turn_on(hass, entity_id=None):
|
|
"""Turn on specified media player or all."""
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
await hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data)
|
|
|
|
|
|
async def async_turn_off(hass, entity_id=None):
|
|
"""Turn off specified media player or all."""
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
await hass.services.async_call(DOMAIN, SERVICE_TURN_OFF, data)
|
|
|
|
|
|
async def async_media_pause(hass, entity_id=None):
|
|
"""Send the media player the command for pause."""
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
await hass.services.async_call(DOMAIN, SERVICE_MEDIA_PAUSE, data)
|
|
|
|
|
|
async def async_media_play(hass, entity_id=None):
|
|
"""Send the media player the command for play/pause."""
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
await hass.services.async_call(DOMAIN, SERVICE_MEDIA_PLAY, data)
|
|
|
|
|
|
async def async_media_stop(hass, entity_id=None):
|
|
"""Send the media player the command for stop."""
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
await hass.services.async_call(DOMAIN, SERVICE_MEDIA_STOP, data)
|
|
|
|
|
|
async def async_media_next_track(hass, entity_id=None):
|
|
"""Send the media player the command for next track."""
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
await hass.services.async_call(DOMAIN, SERVICE_MEDIA_NEXT_TRACK, data)
|
|
|
|
|
|
async def async_media_previous_track(hass, entity_id=None):
|
|
"""Send the media player the command for prev track."""
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
await hass.services.async_call(DOMAIN, SERVICE_MEDIA_PREVIOUS_TRACK, data)
|
|
|
|
|
|
async def async_play_media(hass, media_type, media_id, entity_id=None,
|
|
enqueue=None):
|
|
"""Send the media player the command for playing media."""
|
|
data = {ATTR_MEDIA_CONTENT_TYPE: media_type,
|
|
ATTR_MEDIA_CONTENT_ID: media_id}
|
|
|
|
if entity_id:
|
|
data[ATTR_ENTITY_ID] = entity_id
|
|
|
|
if enqueue:
|
|
data[ATTR_MEDIA_ENQUEUE] = enqueue
|
|
|
|
await hass.services.async_call(DOMAIN, SERVICE_PLAY_MEDIA, data)
|
|
|
|
|
|
class MockDirectvClass:
|
|
"""A fake DirecTV DVR device."""
|
|
|
|
def __init__(self, ip, port=8080, clientAddr='0'):
|
|
"""Initialize the fake DirecTV device."""
|
|
self._host = ip
|
|
self._port = port
|
|
self._device = clientAddr
|
|
self._standby = True
|
|
self._play = False
|
|
|
|
self._locations = LOCATIONS
|
|
|
|
self.attributes = LIVE
|
|
|
|
def get_locations(self):
|
|
"""Mock for get_locations method."""
|
|
test_locations = {
|
|
'locations': self._locations,
|
|
'status': {
|
|
'code': 200,
|
|
'commandResult': 0,
|
|
'msg': 'OK.',
|
|
'query': '/info/getLocations'
|
|
}
|
|
}
|
|
|
|
return test_locations
|
|
|
|
def get_standby(self):
|
|
"""Mock for get_standby method."""
|
|
return self._standby
|
|
|
|
def get_tuned(self):
|
|
"""Mock for get_tuned method."""
|
|
if self._play:
|
|
self.attributes['offset'] = self.attributes['offset']+1
|
|
|
|
test_attributes = self.attributes
|
|
test_attributes['status'] = {
|
|
"code": 200,
|
|
"commandResult": 0,
|
|
"msg": "OK.",
|
|
"query": "/tv/getTuned"
|
|
}
|
|
return test_attributes
|
|
|
|
def key_press(self, keypress):
|
|
"""Mock for key_press method."""
|
|
if keypress == 'poweron':
|
|
self._standby = False
|
|
self._play = True
|
|
elif keypress == 'poweroff':
|
|
self._standby = True
|
|
self._play = False
|
|
elif keypress == 'play':
|
|
self._play = True
|
|
elif keypress == 'pause' or keypress == 'stop':
|
|
self._play = False
|
|
|
|
def tune_channel(self, source):
|
|
"""Mock for tune_channel method."""
|
|
self.attributes['major'] = int(source)
|
|
|
|
|
|
async def test_setup_platform_config(hass):
|
|
"""Test setting up the platform from configuration."""
|
|
with MockDependency('DirectPy'), \
|
|
patch('DirectPy.DIRECTV', new=MockDirectvClass):
|
|
|
|
await async_setup_component(hass, DOMAIN, WORKING_CONFIG)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state
|
|
assert len(hass.states.async_entity_ids('media_player')) == 1
|
|
|
|
|
|
async def test_setup_platform_discover(hass):
|
|
"""Test setting up the platform from discovery."""
|
|
with MockDependency('DirectPy'), \
|
|
patch('DirectPy.DIRECTV', new=MockDirectvClass):
|
|
|
|
hass.async_create_task(
|
|
async_load_platform(hass, DOMAIN, 'directv', DISCOVERY_INFO,
|
|
{'media_player': {}})
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state
|
|
assert len(hass.states.async_entity_ids('media_player')) == 1
|
|
|
|
|
|
async def test_setup_platform_discover_duplicate(hass):
|
|
"""Test setting up the platform from discovery."""
|
|
with MockDependency('DirectPy'), \
|
|
patch('DirectPy.DIRECTV', new=MockDirectvClass):
|
|
|
|
await async_setup_component(hass, DOMAIN, WORKING_CONFIG)
|
|
await hass.async_block_till_done()
|
|
hass.async_create_task(
|
|
async_load_platform(hass, DOMAIN, 'directv', DISCOVERY_INFO,
|
|
{'media_player': {}})
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state
|
|
assert len(hass.states.async_entity_ids('media_player')) == 1
|
|
|
|
|
|
async def test_setup_platform_discover_client(hass):
|
|
"""Test setting up the platform from discovery."""
|
|
LOCATIONS.append({
|
|
'locationName': 'Client 1',
|
|
'clientAddr': '1'
|
|
})
|
|
LOCATIONS.append({
|
|
'locationName': 'Client 2',
|
|
'clientAddr': '2'
|
|
})
|
|
|
|
with MockDependency('DirectPy'), \
|
|
patch('DirectPy.DIRECTV', new=MockDirectvClass):
|
|
|
|
await async_setup_component(hass, DOMAIN, WORKING_CONFIG)
|
|
await hass.async_block_till_done()
|
|
|
|
hass.async_create_task(
|
|
async_load_platform(hass, DOMAIN, 'directv', DISCOVERY_INFO,
|
|
{'media_player': {}})
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
del LOCATIONS[-1]
|
|
del LOCATIONS[-1]
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state
|
|
state = hass.states.get('media_player.client_1')
|
|
assert state
|
|
state = hass.states.get('media_player.client_2')
|
|
assert state
|
|
|
|
assert len(hass.states.async_entity_ids('media_player')) == 3
|
|
|
|
|
|
async def test_supported_features(hass, platforms):
|
|
"""Test supported features."""
|
|
# Features supported for main DVR
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert SUPPORT_PAUSE | SUPPORT_TURN_ON | SUPPORT_TURN_OFF |\
|
|
SUPPORT_PLAY_MEDIA | SUPPORT_STOP | SUPPORT_NEXT_TRACK |\
|
|
SUPPORT_PREVIOUS_TRACK | SUPPORT_PLAY ==\
|
|
state.attributes.get('supported_features')
|
|
|
|
# Feature supported for clients.
|
|
state = hass.states.get(CLIENT_ENTITY_ID)
|
|
assert SUPPORT_PAUSE |\
|
|
SUPPORT_PLAY_MEDIA | SUPPORT_STOP | SUPPORT_NEXT_TRACK |\
|
|
SUPPORT_PREVIOUS_TRACK | SUPPORT_PLAY ==\
|
|
state.attributes.get('supported_features')
|
|
|
|
|
|
async def test_check_attributes(hass, platforms, mock_now):
|
|
"""Test attributes."""
|
|
next_update = mock_now + timedelta(minutes=5)
|
|
with patch('homeassistant.util.dt.utcnow', return_value=next_update):
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done()
|
|
|
|
# Start playing TV
|
|
with patch('homeassistant.util.dt.utcnow',
|
|
return_value=next_update):
|
|
await async_media_play(hass, CLIENT_ENTITY_ID)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(CLIENT_ENTITY_ID)
|
|
assert state.state == STATE_PLAYING
|
|
|
|
assert state.attributes.get(ATTR_MEDIA_CONTENT_ID) == \
|
|
RECORDING['programId']
|
|
assert state.attributes.get(ATTR_MEDIA_CONTENT_TYPE) == \
|
|
MEDIA_TYPE_TVSHOW
|
|
assert state.attributes.get(ATTR_MEDIA_DURATION) == \
|
|
RECORDING['duration']
|
|
assert state.attributes.get(ATTR_MEDIA_POSITION) == 2
|
|
assert state.attributes.get(
|
|
ATTR_MEDIA_POSITION_UPDATED_AT) == next_update
|
|
assert state.attributes.get(ATTR_MEDIA_TITLE) == RECORDING['title']
|
|
assert state.attributes.get(ATTR_MEDIA_SERIES_TITLE) == \
|
|
RECORDING['episodeTitle']
|
|
assert state.attributes.get(ATTR_MEDIA_CHANNEL) == \
|
|
"{} ({})".format(RECORDING['callsign'], RECORDING['major'])
|
|
assert state.attributes.get(ATTR_INPUT_SOURCE) == RECORDING['major']
|
|
assert state.attributes.get(ATTR_MEDIA_CURRENTLY_RECORDING) == \
|
|
RECORDING['isRecording']
|
|
assert state.attributes.get(ATTR_MEDIA_RATING) == RECORDING['rating']
|
|
assert state.attributes.get(ATTR_MEDIA_RECORDED)
|
|
assert state.attributes.get(ATTR_MEDIA_START_TIME) == \
|
|
datetime(2018, 11, 10, 19, 0, tzinfo=dt_util.UTC)
|
|
|
|
# Test to make sure that ATTR_MEDIA_POSITION_UPDATED_AT is not
|
|
# updated if TV is paused.
|
|
with patch('homeassistant.util.dt.utcnow',
|
|
return_value=next_update + timedelta(minutes=5)):
|
|
await async_media_pause(hass, CLIENT_ENTITY_ID)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(CLIENT_ENTITY_ID)
|
|
assert state.state == STATE_PAUSED
|
|
assert state.attributes.get(
|
|
ATTR_MEDIA_POSITION_UPDATED_AT) == next_update
|
|
|
|
|
|
async def test_main_services(hass, platforms, main_dtv, mock_now):
|
|
"""Test the different services."""
|
|
next_update = mock_now + timedelta(minutes=5)
|
|
with patch('homeassistant.util.dt.utcnow', return_value=next_update):
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done()
|
|
# DVR starts in off state.
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state == STATE_OFF
|
|
|
|
# All these should call key_press in our class.
|
|
with patch.object(main_dtv, 'key_press',
|
|
wraps=main_dtv.key_press) as mock_key_press, \
|
|
patch.object(main_dtv, 'tune_channel',
|
|
wraps=main_dtv.tune_channel) as mock_tune_channel, \
|
|
patch.object(main_dtv, 'get_tuned',
|
|
wraps=main_dtv.get_tuned) as mock_get_tuned, \
|
|
patch.object(main_dtv, 'get_standby',
|
|
wraps=main_dtv.get_standby) as mock_get_standby:
|
|
|
|
# Turn main DVR on. When turning on DVR is playing.
|
|
await async_turn_on(hass, MAIN_ENTITY_ID)
|
|
await hass.async_block_till_done()
|
|
assert mock_key_press.called
|
|
assert mock_key_press.call_args == call('poweron')
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state == STATE_PLAYING
|
|
|
|
# Pause live TV.
|
|
await async_media_pause(hass, MAIN_ENTITY_ID)
|
|
await hass.async_block_till_done()
|
|
assert mock_key_press.called
|
|
assert mock_key_press.call_args == call('pause')
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state == STATE_PAUSED
|
|
|
|
# Start play again for live TV.
|
|
await async_media_play(hass, MAIN_ENTITY_ID)
|
|
await hass.async_block_till_done()
|
|
assert mock_key_press.called
|
|
assert mock_key_press.call_args == call('play')
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state == STATE_PLAYING
|
|
|
|
# Change channel, currently it should be 202
|
|
assert state.attributes.get('source') == 202
|
|
await async_play_media(hass, 'channel', 7, MAIN_ENTITY_ID)
|
|
await hass.async_block_till_done()
|
|
assert mock_tune_channel.called
|
|
assert mock_tune_channel.call_args == call('7')
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.attributes.get('source') == 7
|
|
|
|
# Stop live TV.
|
|
await async_media_stop(hass, MAIN_ENTITY_ID)
|
|
await hass.async_block_till_done()
|
|
assert mock_key_press.called
|
|
assert mock_key_press.call_args == call('stop')
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state == STATE_PAUSED
|
|
|
|
# Turn main DVR off.
|
|
await async_turn_off(hass, MAIN_ENTITY_ID)
|
|
await hass.async_block_till_done()
|
|
assert mock_key_press.called
|
|
assert mock_key_press.call_args == call('poweroff')
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state == STATE_OFF
|
|
|
|
# There should have been 6 calls to check if DVR is in standby
|
|
assert main_dtv.get_standby.call_count == 6
|
|
assert mock_get_standby.call_count == 6
|
|
# There should be 5 calls to get current info (only 1 time it will
|
|
# not be called as DVR is in standby.)
|
|
assert main_dtv.get_tuned.call_count == 5
|
|
assert mock_get_tuned.call_count == 5
|
|
|
|
|
|
async def test_available(hass, platforms, main_dtv, mock_now):
|
|
"""Test available status."""
|
|
next_update = mock_now + timedelta(minutes=5)
|
|
with patch('homeassistant.util.dt.utcnow', return_value=next_update):
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done()
|
|
|
|
# Confirm service is currently set to available.
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state != STATE_UNAVAILABLE
|
|
|
|
# Make update fail 1st time
|
|
next_update = next_update + timedelta(minutes=5)
|
|
with patch.object(
|
|
main_dtv, 'get_standby', side_effect=requests.RequestException), \
|
|
patch('homeassistant.util.dt.utcnow', return_value=next_update):
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state != STATE_UNAVAILABLE
|
|
|
|
# Make update fail 2nd time within 1 minute
|
|
next_update = next_update + timedelta(seconds=30)
|
|
with patch.object(
|
|
main_dtv, 'get_standby', side_effect=requests.RequestException), \
|
|
patch('homeassistant.util.dt.utcnow', return_value=next_update):
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state != STATE_UNAVAILABLE
|
|
|
|
# Make update fail 3rd time more then a minute after 1st failure
|
|
next_update = next_update + timedelta(minutes=1)
|
|
with patch.object(
|
|
main_dtv, 'get_standby', side_effect=requests.RequestException), \
|
|
patch('homeassistant.util.dt.utcnow', return_value=next_update):
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done()
|
|
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state == STATE_UNAVAILABLE
|
|
|
|
# Recheck state, update should work again.
|
|
next_update = next_update + timedelta(minutes=5)
|
|
with patch('homeassistant.util.dt.utcnow', return_value=next_update):
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done()
|
|
state = hass.states.get(MAIN_ENTITY_ID)
|
|
assert state.state != STATE_UNAVAILABLE
|