Merge pull request #1573 from MartinHjelmare/service-warnings
Log error for servicecall without required datapull/1579/head
commit
0bf13dbf26
|
@ -19,6 +19,8 @@ from homeassistant.const import (
|
|||
SERVICE_MEDIA_PLAY_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PAUSE,
|
||||
SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PREVIOUS_TRACK, SERVICE_MEDIA_SEEK)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = 'media_player'
|
||||
SCAN_INTERVAL = 10
|
||||
|
||||
|
@ -230,11 +232,9 @@ def setup(hass, config):
|
|||
|
||||
def media_player_service_handler(service):
|
||||
"""Map services to methods on MediaPlayerDevice."""
|
||||
target_players = component.extract_from_service(service)
|
||||
|
||||
method = SERVICE_TO_METHOD[service.service]
|
||||
|
||||
for player in target_players:
|
||||
for player in component.extract_from_service(service):
|
||||
getattr(player, method)()
|
||||
|
||||
if player.should_poll:
|
||||
|
@ -246,14 +246,15 @@ def setup(hass, config):
|
|||
|
||||
def volume_set_service(service):
|
||||
"""Set specified volume on the media player."""
|
||||
target_players = component.extract_from_service(service)
|
||||
volume = service.data.get(ATTR_MEDIA_VOLUME_LEVEL)
|
||||
|
||||
if ATTR_MEDIA_VOLUME_LEVEL not in service.data:
|
||||
if volume is None:
|
||||
_LOGGER.error(
|
||||
'Received call to %s without attribute %s',
|
||||
service.service, ATTR_MEDIA_VOLUME_LEVEL)
|
||||
return
|
||||
|
||||
volume = service.data[ATTR_MEDIA_VOLUME_LEVEL]
|
||||
|
||||
for player in target_players:
|
||||
for player in component.extract_from_service(service):
|
||||
player.set_volume_level(volume)
|
||||
|
||||
if player.should_poll:
|
||||
|
@ -264,14 +265,15 @@ def setup(hass, config):
|
|||
|
||||
def volume_mute_service(service):
|
||||
"""Mute (true) or unmute (false) the media player."""
|
||||
target_players = component.extract_from_service(service)
|
||||
mute = service.data.get(ATTR_MEDIA_VOLUME_MUTED)
|
||||
|
||||
if ATTR_MEDIA_VOLUME_MUTED not in service.data:
|
||||
if mute is None:
|
||||
_LOGGER.error(
|
||||
'Received call to %s without attribute %s',
|
||||
service.service, ATTR_MEDIA_VOLUME_MUTED)
|
||||
return
|
||||
|
||||
mute = service.data[ATTR_MEDIA_VOLUME_MUTED]
|
||||
|
||||
for player in target_players:
|
||||
for player in component.extract_from_service(service):
|
||||
player.mute_volume(mute)
|
||||
|
||||
if player.should_poll:
|
||||
|
@ -282,14 +284,15 @@ def setup(hass, config):
|
|||
|
||||
def media_seek_service(service):
|
||||
"""Seek to a position."""
|
||||
target_players = component.extract_from_service(service)
|
||||
position = service.data.get(ATTR_MEDIA_SEEK_POSITION)
|
||||
|
||||
if ATTR_MEDIA_SEEK_POSITION not in service.data:
|
||||
if position is None:
|
||||
_LOGGER.error(
|
||||
'Received call to %s without attribute %s',
|
||||
service.service, ATTR_MEDIA_SEEK_POSITION)
|
||||
return
|
||||
|
||||
position = service.data[ATTR_MEDIA_SEEK_POSITION]
|
||||
|
||||
for player in target_players:
|
||||
for player in component.extract_from_service(service):
|
||||
player.media_seek(position)
|
||||
|
||||
if player.should_poll:
|
||||
|
@ -303,10 +306,12 @@ def setup(hass, config):
|
|||
media_type = service.data.get(ATTR_MEDIA_CONTENT_TYPE)
|
||||
media_id = service.data.get(ATTR_MEDIA_CONTENT_ID)
|
||||
|
||||
if media_type is None:
|
||||
return
|
||||
|
||||
if media_id is None:
|
||||
if media_type is None or media_id is None:
|
||||
missing_attr = (ATTR_MEDIA_CONTENT_TYPE if media_type is None
|
||||
else ATTR_MEDIA_CONTENT_ID)
|
||||
_LOGGER.error(
|
||||
'Received call to %s without attribute %s',
|
||||
service.service, missing_attr)
|
||||
return
|
||||
|
||||
for player in component.extract_from_service(service):
|
||||
|
|
|
@ -239,7 +239,7 @@ class DemoMusicPlayer(AbstractDemoPlayer):
|
|||
if self._cur_track > 0:
|
||||
support |= SUPPORT_PREVIOUS_TRACK
|
||||
|
||||
if self._cur_track < len(self.tracks)-1:
|
||||
if self._cur_track < len(self.tracks) - 1:
|
||||
support |= SUPPORT_NEXT_TRACK
|
||||
|
||||
return support
|
||||
|
@ -252,7 +252,7 @@ class DemoMusicPlayer(AbstractDemoPlayer):
|
|||
|
||||
def media_next_track(self):
|
||||
"""Send next track command."""
|
||||
if self._cur_track < len(self.tracks)-1:
|
||||
if self._cur_track < len(self.tracks) - 1:
|
||||
self._cur_track += 1
|
||||
self.update_ha_state()
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@ def setup(hass, config):
|
|||
message = call.data.get(ATTR_MESSAGE)
|
||||
|
||||
if message is None:
|
||||
_LOGGER.error(
|
||||
'Received call to %s without attribute %s',
|
||||
call.service, ATTR_MESSAGE)
|
||||
return
|
||||
|
||||
title = template.render(
|
||||
|
|
|
@ -45,7 +45,7 @@ class FileNotificationService(BaseNotificationService):
|
|||
title = '{} notifications (Log started: {})\n{}\n'.format(
|
||||
kwargs.get(ATTR_TITLE),
|
||||
dt_util.strip_microseconds(dt_util.utcnow()),
|
||||
'-'*80)
|
||||
'-' * 80)
|
||||
file.write(title)
|
||||
|
||||
if self.add_timestamp == 1:
|
||||
|
|
|
@ -123,6 +123,9 @@ def setup(hass, config):
|
|||
service.data.get(ATTR_TEMPERATURE), float)
|
||||
|
||||
if temperature is None:
|
||||
_LOGGER.error(
|
||||
"Received call to %s without attribute %s",
|
||||
SERVICE_SET_TEMPERATURE, ATTR_TEMPERATURE)
|
||||
return
|
||||
|
||||
for thermostat in target_thermostats:
|
||||
|
|
|
@ -11,8 +11,8 @@ from homeassistant.const import TEMP_CELCIUS, TEMP_FAHRENHEIT
|
|||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup the Demo thermostats."""
|
||||
add_devices([
|
||||
DemoThermostat("Nest", 21, TEMP_CELCIUS, False, 19),
|
||||
DemoThermostat("Thermostat", 68, TEMP_FAHRENHEIT, True, 77),
|
||||
DemoThermostat("Nest", 21, TEMP_CELCIUS, False, 19, False),
|
||||
DemoThermostat("Thermostat", 68, TEMP_FAHRENHEIT, True, 77, True),
|
||||
])
|
||||
|
||||
|
||||
|
@ -21,13 +21,14 @@ class DemoThermostat(ThermostatDevice):
|
|||
"""Representation of a demo thermostat."""
|
||||
|
||||
def __init__(self, name, target_temperature, unit_of_measurement,
|
||||
away, current_temperature):
|
||||
away, current_temperature, is_fan_on):
|
||||
"""Initialize the thermostat."""
|
||||
self._name = name
|
||||
self._target_temperature = target_temperature
|
||||
self._unit_of_measurement = unit_of_measurement
|
||||
self._away = away
|
||||
self._current_temperature = current_temperature
|
||||
self._is_fan_on = is_fan_on
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
|
@ -59,6 +60,11 @@ class DemoThermostat(ThermostatDevice):
|
|||
"""Return if away mode is on."""
|
||||
return self._away
|
||||
|
||||
@property
|
||||
def is_fan_on(self):
|
||||
"""Return true if the fan is on."""
|
||||
return self._is_fan_on
|
||||
|
||||
def set_temperature(self, temperature):
|
||||
"""Set new target temperature."""
|
||||
self._target_temperature = temperature
|
||||
|
@ -70,3 +76,11 @@ class DemoThermostat(ThermostatDevice):
|
|||
def turn_away_mode_off(self):
|
||||
"""Turn away mode off."""
|
||||
self._away = False
|
||||
|
||||
def turn_fan_on(self):
|
||||
"""Turn fan on."""
|
||||
self._is_fan_on = True
|
||||
|
||||
def turn_fan_off(self):
|
||||
"""Turn fan off."""
|
||||
self._is_fan_on = False
|
||||
|
|
|
@ -25,6 +25,11 @@ class TestDemoMediaPlayer(unittest.TestCase):
|
|||
state = self.hass.states.get(entity_id)
|
||||
assert 1.0 == state.attributes.get('volume_level')
|
||||
|
||||
mp.set_volume_level(self.hass, None, entity_id)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(entity_id)
|
||||
assert 1.0 == state.attributes.get('volume_level')
|
||||
|
||||
mp.set_volume_level(self.hass, 0.5, entity_id)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(entity_id)
|
||||
|
@ -41,6 +46,12 @@ class TestDemoMediaPlayer(unittest.TestCase):
|
|||
assert 0.5 == state.attributes.get('volume_level')
|
||||
|
||||
assert False is state.attributes.get('is_volume_muted')
|
||||
|
||||
mp.mute_volume(self.hass, None, entity_id)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(entity_id)
|
||||
assert False is state.attributes.get('is_volume_muted')
|
||||
|
||||
mp.mute_volume(self.hass, True, entity_id)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(entity_id)
|
||||
|
@ -87,7 +98,7 @@ class TestDemoMediaPlayer(unittest.TestCase):
|
|||
assert self.hass.states.is_state(entity_id, 'playing')
|
||||
|
||||
def test_prev_next_track(self):
|
||||
"""Test media_next_track and media_prevoius_track ."""
|
||||
"""Test media_next_track and media_previous_track ."""
|
||||
assert mp.setup(self.hass, {'media_player': {'platform': 'demo'}})
|
||||
state = self.hass.states.get(entity_id)
|
||||
assert 1 == state.attributes.get('media_track')
|
||||
|
@ -115,6 +126,27 @@ class TestDemoMediaPlayer(unittest.TestCase):
|
|||
assert 0 < (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
|
||||
assert mp.setup(self.hass, {'media_player': {'platform': 'demo'}})
|
||||
ent_id = 'media_player.lounge_room'
|
||||
state = self.hass.states.get(ent_id)
|
||||
assert 1 == state.attributes.get('media_episode')
|
||||
assert 0 == (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
|
||||
mp.media_next_track(self.hass, ent_id)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ent_id)
|
||||
assert 2 == state.attributes.get('media_episode')
|
||||
assert 0 < (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
|
||||
mp.media_previous_track(self.hass, ent_id)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ent_id)
|
||||
assert 1 == state.attributes.get('media_episode')
|
||||
assert 0 == (mp.SUPPORT_PREVIOUS_TRACK &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
|
||||
@patch('homeassistant.components.media_player.demo.DemoYoutubePlayer.'
|
||||
'media_seek')
|
||||
def test_play_media(self, mock_seek):
|
||||
|
@ -126,6 +158,13 @@ class TestDemoMediaPlayer(unittest.TestCase):
|
|||
state.attributes.get('supported_media_commands'))
|
||||
assert state.attributes.get('media_content_id') is not None
|
||||
|
||||
mp.play_media(self.hass, None, 'some_id', ent_id)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ent_id)
|
||||
assert 0 < (mp.SUPPORT_PLAY_MEDIA &
|
||||
state.attributes.get('supported_media_commands'))
|
||||
assert not 'some_id' == state.attributes.get('media_content_id')
|
||||
|
||||
mp.play_media(self.hass, 'youtube', 'some_id', ent_id)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ent_id)
|
||||
|
@ -133,6 +172,9 @@ class TestDemoMediaPlayer(unittest.TestCase):
|
|||
state.attributes.get('supported_media_commands'))
|
||||
assert 'some_id' == state.attributes.get('media_content_id')
|
||||
|
||||
assert not mock_seek.called
|
||||
mp.media_seek(self.hass, None, ent_id)
|
||||
self.hass.pool.block_till_done()
|
||||
assert not mock_seek.called
|
||||
mp.media_seek(self.hass, 100, ent_id)
|
||||
self.hass.pool.block_till_done()
|
||||
|
|
|
@ -25,8 +25,37 @@ class MockMediaPlayer(media_player.MediaPlayerDevice):
|
|||
self._media_title = None
|
||||
self._supported_media_commands = 0
|
||||
|
||||
self.turn_off_service_calls = mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_TURN_OFF)
|
||||
self.service_calls = {
|
||||
'turn_on': mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_TURN_ON),
|
||||
'turn_off': mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_TURN_OFF),
|
||||
'mute_volume': mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_MUTE),
|
||||
'set_volume_level': mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_SET),
|
||||
'media_play': mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_MEDIA_PLAY),
|
||||
'media_pause': mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_MEDIA_PAUSE),
|
||||
'media_previous_track': mock_service(
|
||||
hass, media_player.DOMAIN,
|
||||
media_player.SERVICE_MEDIA_PREVIOUS_TRACK),
|
||||
'media_next_track': mock_service(
|
||||
hass, media_player.DOMAIN,
|
||||
media_player.SERVICE_MEDIA_NEXT_TRACK),
|
||||
'media_seek': mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_MEDIA_SEEK),
|
||||
'play_media': mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_PLAY_MEDIA),
|
||||
'volume_up': mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_UP),
|
||||
'volume_down': mock_service(
|
||||
hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_DOWN),
|
||||
'media_play_pause': mock_service(
|
||||
hass, media_player.DOMAIN,
|
||||
media_player.SERVICE_MEDIA_PLAY_PAUSE),
|
||||
}
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
@ -97,23 +126,26 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
self.mock_state_switch_id = switch.ENTITY_ID_FORMAT.format('state')
|
||||
self.hass.states.set(self.mock_state_switch_id, STATE_OFF)
|
||||
|
||||
self.config_children_only = \
|
||||
{'name': 'test', 'platform': 'universal',
|
||||
'children': [media_player.ENTITY_ID_FORMAT.format('mock1'),
|
||||
media_player.ENTITY_ID_FORMAT.format('mock2')]}
|
||||
self.config_children_and_attr = \
|
||||
{'name': 'test', 'platform': 'universal',
|
||||
'children': [media_player.ENTITY_ID_FORMAT.format('mock1'),
|
||||
media_player.ENTITY_ID_FORMAT.format('mock2')],
|
||||
'attributes': {
|
||||
'is_volume_muted': self.mock_mute_switch_id,
|
||||
'state': self.mock_state_switch_id}}
|
||||
self.config_children_only = {
|
||||
'name': 'test', 'platform': 'universal',
|
||||
'children': [media_player.ENTITY_ID_FORMAT.format('mock1'),
|
||||
media_player.ENTITY_ID_FORMAT.format('mock2')]
|
||||
}
|
||||
self.config_children_and_attr = {
|
||||
'name': 'test', 'platform': 'universal',
|
||||
'children': [media_player.ENTITY_ID_FORMAT.format('mock1'),
|
||||
media_player.ENTITY_ID_FORMAT.format('mock2')],
|
||||
'attributes': {
|
||||
'is_volume_muted': self.mock_mute_switch_id,
|
||||
'state': self.mock_state_switch_id
|
||||
}
|
||||
}
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
"""Stop everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_check_config_children_only(self):
|
||||
def test_config_children_only(self):
|
||||
"""Check config with only children."""
|
||||
config_start = copy(self.config_children_only)
|
||||
del config_start['platform']
|
||||
|
@ -125,7 +157,7 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
self.assertTrue(response)
|
||||
self.assertEqual(config_start, self.config_children_only)
|
||||
|
||||
def test_check_config_children_and_attr(self):
|
||||
def test_config_children_and_attr(self):
|
||||
"""Check config with children and attributes."""
|
||||
config_start = copy(self.config_children_and_attr)
|
||||
del config_start['platform']
|
||||
|
@ -136,13 +168,13 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
self.assertTrue(response)
|
||||
self.assertEqual(config_start, self.config_children_and_attr)
|
||||
|
||||
def test_check_config_no_name(self):
|
||||
def test_config_no_name(self):
|
||||
"""Check config with no Name entry."""
|
||||
response = universal.validate_config({'platform': 'universal'})
|
||||
|
||||
self.assertFalse(response)
|
||||
|
||||
def test_check_config_bad_children(self):
|
||||
def test_config_bad_children(self):
|
||||
"""Check config with bad children entry."""
|
||||
config_no_children = {'name': 'test', 'platform': 'universal'}
|
||||
config_bad_children = {'name': 'test', 'children': {},
|
||||
|
@ -156,7 +188,7 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
self.assertTrue(response)
|
||||
self.assertEqual([], config_bad_children['children'])
|
||||
|
||||
def test_check_config_bad_commands(self):
|
||||
def test_config_bad_commands(self):
|
||||
"""Check config with bad commands entry."""
|
||||
config = {'name': 'test', 'commands': [], 'platform': 'universal'}
|
||||
|
||||
|
@ -164,7 +196,7 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
self.assertTrue(response)
|
||||
self.assertEqual({}, config['commands'])
|
||||
|
||||
def test_check_config_bad_attributes(self):
|
||||
def test_config_bad_attributes(self):
|
||||
"""Check config with bad attributes."""
|
||||
config = {'name': 'test', 'attributes': [], 'platform': 'universal'}
|
||||
|
||||
|
@ -172,7 +204,7 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
self.assertTrue(response)
|
||||
self.assertEqual({}, config['attributes'])
|
||||
|
||||
def test_check_config_bad_key(self):
|
||||
def test_config_bad_key(self):
|
||||
"""Check config with bad key."""
|
||||
config = {'name': 'test', 'asdf': 5, 'platform': 'universal'}
|
||||
|
||||
|
@ -183,6 +215,7 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
def test_platform_setup(self):
|
||||
"""Test platform setup."""
|
||||
config = {'name': 'test', 'platform': 'universal'}
|
||||
bad_config = {'platform': 'universal'}
|
||||
entities = []
|
||||
|
||||
def add_devices(new_entities):
|
||||
|
@ -190,8 +223,10 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
for dev in new_entities:
|
||||
entities.append(dev)
|
||||
|
||||
universal.setup_platform(self.hass, config, add_devices)
|
||||
universal.setup_platform(self.hass, bad_config, add_devices)
|
||||
self.assertEqual(0, len(entities))
|
||||
|
||||
universal.setup_platform(self.hass, config, add_devices)
|
||||
self.assertEqual(1, len(entities))
|
||||
self.assertEqual('test', entities[0].name)
|
||||
|
||||
|
@ -263,6 +298,15 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
|
||||
self.assertEqual(config['name'], ump.name)
|
||||
|
||||
def test_polling(self):
|
||||
"""Test should_poll property."""
|
||||
config = self.config_children_only
|
||||
universal.validate_config(config)
|
||||
|
||||
ump = universal.UniversalMediaPlayer(self.hass, **config)
|
||||
|
||||
self.assertEqual(False, ump.should_poll)
|
||||
|
||||
def test_state_children_only(self):
|
||||
"""Test media player state with only children."""
|
||||
config = self.config_children_only
|
||||
|
@ -388,8 +432,7 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name'])
|
||||
ump.update()
|
||||
|
||||
self.mock_mp_1._supported_media_commands = \
|
||||
universal.SUPPORT_VOLUME_SET
|
||||
self.mock_mp_1._supported_media_commands = universal.SUPPORT_VOLUME_SET
|
||||
self.mock_mp_1._state = STATE_PLAYING
|
||||
self.mock_mp_1.update_ha_state()
|
||||
ump.update()
|
||||
|
@ -400,7 +443,7 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
self.assertEqual(check_flags, ump.supported_media_commands)
|
||||
|
||||
def test_service_call_to_child(self):
|
||||
"""Test a service call that should be routed to a child."""
|
||||
"""Test service calls that should be routed to a child."""
|
||||
config = self.config_children_only
|
||||
universal.validate_config(config)
|
||||
|
||||
|
@ -413,13 +456,53 @@ class TestMediaPlayer(unittest.TestCase):
|
|||
ump.update()
|
||||
|
||||
ump.turn_off()
|
||||
self.assertEqual(1, len(self.mock_mp_2.turn_off_service_calls))
|
||||
self.assertEqual(1, len(self.mock_mp_2.service_calls['turn_off']))
|
||||
|
||||
ump.turn_on()
|
||||
self.assertEqual(1, len(self.mock_mp_2.service_calls['turn_on']))
|
||||
|
||||
ump.mute_volume(True)
|
||||
self.assertEqual(1, len(self.mock_mp_2.service_calls['mute_volume']))
|
||||
|
||||
ump.set_volume_level(0.5)
|
||||
self.assertEqual(
|
||||
1, len(self.mock_mp_2.service_calls['set_volume_level']))
|
||||
|
||||
ump.media_play()
|
||||
self.assertEqual(1, len(self.mock_mp_2.service_calls['media_play']))
|
||||
|
||||
ump.media_pause()
|
||||
self.assertEqual(1, len(self.mock_mp_2.service_calls['media_pause']))
|
||||
|
||||
ump.media_previous_track()
|
||||
self.assertEqual(
|
||||
1, len(self.mock_mp_2.service_calls['media_previous_track']))
|
||||
|
||||
ump.media_next_track()
|
||||
self.assertEqual(
|
||||
1, len(self.mock_mp_2.service_calls['media_next_track']))
|
||||
|
||||
ump.media_seek(100)
|
||||
self.assertEqual(1, len(self.mock_mp_2.service_calls['media_seek']))
|
||||
|
||||
ump.play_media('movie', 'batman')
|
||||
self.assertEqual(1, len(self.mock_mp_2.service_calls['play_media']))
|
||||
|
||||
ump.volume_up()
|
||||
self.assertEqual(1, len(self.mock_mp_2.service_calls['volume_up']))
|
||||
|
||||
ump.volume_down()
|
||||
self.assertEqual(1, len(self.mock_mp_2.service_calls['volume_down']))
|
||||
|
||||
ump.media_play_pause()
|
||||
self.assertEqual(
|
||||
1, len(self.mock_mp_2.service_calls['media_play_pause']))
|
||||
|
||||
def test_service_call_to_command(self):
|
||||
"""Test service call to command."""
|
||||
config = self.config_children_only
|
||||
config['commands'] = \
|
||||
{'turn_off': {'service': 'test.turn_off', 'data': {}}}
|
||||
config['commands'] = {'turn_off': {
|
||||
'service': 'test.turn_off', 'data': {}}}
|
||||
universal.validate_config(config)
|
||||
|
||||
service = mock_service(self.hass, 'test', 'turn_off')
|
||||
|
|
|
@ -3,8 +3,10 @@ import os
|
|||
import tempfile
|
||||
import unittest
|
||||
|
||||
from homeassistant import core
|
||||
import homeassistant.components.notify as notify
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
|
@ -13,12 +15,27 @@ class TestCommandLine(unittest.TestCase):
|
|||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = core.HomeAssistant()
|
||||
self.hass = get_test_home_assistant()
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
"""Stop down everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_bad_config(self):
|
||||
"""Test set up the platform with bad/missing config."""
|
||||
self.assertFalse(notify.setup(self.hass, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'bad_platform',
|
||||
}
|
||||
}))
|
||||
self.assertFalse(notify.setup(self.hass, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'command_line',
|
||||
}
|
||||
}))
|
||||
|
||||
def test_command_line_output(self):
|
||||
"""Test the command line output."""
|
||||
with tempfile.TemporaryDirectory() as tempdirname:
|
||||
|
@ -41,7 +58,7 @@ class TestCommandLine(unittest.TestCase):
|
|||
|
||||
@patch('homeassistant.components.notify.command_line._LOGGER.error')
|
||||
def test_error_for_none_zero_exit_code(self, mock_error):
|
||||
"""Test if an error if logged for non zero exit codes."""
|
||||
"""Test if an error is logged for non zero exit codes."""
|
||||
self.assertTrue(notify.setup(self.hass, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
|
|
|
@ -30,6 +30,12 @@ class TestNotifyDemo(unittest.TestCase):
|
|||
""""Stop down everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_sending_none_message(self):
|
||||
"""Test send with None as message."""
|
||||
notify.send_message(self.hass, None)
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertTrue(len(self.events) == 0)
|
||||
|
||||
def test_sending_templated_message(self):
|
||||
"""Send a templated message."""
|
||||
self.hass.states.set('sensor.temperature', 10)
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
"""The tests for the notify file platform."""
|
||||
import os
|
||||
import unittest
|
||||
import tempfile
|
||||
|
||||
import homeassistant.components.notify as notify
|
||||
from homeassistant.components.notify import (
|
||||
ATTR_TITLE_DEFAULT)
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
|
||||
class TestNotifyFile(unittest.TestCase):
|
||||
"""Test the file notify."""
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
""""Stop down everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_bad_config(self):
|
||||
"""Test set up the platform with bad/missing config."""
|
||||
self.assertFalse(notify.setup(self.hass, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'file',
|
||||
}
|
||||
}))
|
||||
|
||||
def test_notify_file(self):
|
||||
"""Test the notify file output."""
|
||||
with tempfile.TemporaryDirectory() as tempdirname:
|
||||
filename = os.path.join(tempdirname, 'notify.txt')
|
||||
message = 'one, two, testing, testing'
|
||||
self.assertTrue(notify.setup(self.hass, {
|
||||
'notify': {
|
||||
'name': 'test',
|
||||
'platform': 'file',
|
||||
'filename': filename,
|
||||
'timestamp': 0
|
||||
}
|
||||
}))
|
||||
title = '{} notifications (Log started: {})\n{}\n'.format(
|
||||
ATTR_TITLE_DEFAULT,
|
||||
dt_util.strip_microseconds(dt_util.utcnow()),
|
||||
'-' * 80)
|
||||
|
||||
self.hass.services.call('notify', 'test', {'message': message},
|
||||
blocking=True)
|
||||
|
||||
result = open(filename).read()
|
||||
self.assertEqual(result, "{}{}\n".format(title, message))
|
|
@ -0,0 +1,101 @@
|
|||
"""The tests for the demo thermostat."""
|
||||
import unittest
|
||||
|
||||
from homeassistant.const import (
|
||||
TEMP_CELCIUS,
|
||||
)
|
||||
from homeassistant.components import thermostat
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
|
||||
ENTITY_NEST = 'thermostat.nest'
|
||||
|
||||
|
||||
class TestDemoThermostat(unittest.TestCase):
|
||||
"""Test the Heat Control thermostat."""
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
self.hass.config.temperature_unit = TEMP_CELCIUS
|
||||
self.assertTrue(thermostat.setup(self.hass, {'thermostat': {
|
||||
'platform': 'demo',
|
||||
}}))
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
"""Stop down everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_setup_params(self):
|
||||
"""Test the inititial parameters."""
|
||||
state = self.hass.states.get(ENTITY_NEST)
|
||||
self.assertEqual(21, state.attributes.get('temperature'))
|
||||
self.assertEqual('off', state.attributes.get('away_mode'))
|
||||
self.assertEqual(19, state.attributes.get('current_temperature'))
|
||||
self.assertEqual('off', state.attributes.get('fan'))
|
||||
|
||||
def test_default_setup_params(self):
|
||||
"""Test the setup with default parameters."""
|
||||
state = self.hass.states.get(ENTITY_NEST)
|
||||
self.assertEqual(7, state.attributes.get('min_temp'))
|
||||
self.assertEqual(35, state.attributes.get('max_temp'))
|
||||
|
||||
def test_set_target_temp_bad_attr(self):
|
||||
"""Test setting the target temperature without required attribute."""
|
||||
self.assertEqual('21', self.hass.states.get(ENTITY_NEST).state)
|
||||
thermostat.set_temperature(self.hass, None, ENTITY_NEST)
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertEqual('21', self.hass.states.get(ENTITY_NEST).state)
|
||||
|
||||
def test_set_target_temp(self):
|
||||
"""Test the setting of the target temperature."""
|
||||
thermostat.set_temperature(self.hass, 30, ENTITY_NEST)
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertEqual('30.0', self.hass.states.get(ENTITY_NEST).state)
|
||||
|
||||
def test_set_away_mode_bad_attr(self):
|
||||
"""Test setting the away mode without required attribute."""
|
||||
state = self.hass.states.get(ENTITY_NEST)
|
||||
self.assertEqual('off', state.attributes.get('away_mode'))
|
||||
thermostat.set_away_mode(self.hass, None, ENTITY_NEST)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ENTITY_NEST)
|
||||
self.assertEqual('off', state.attributes.get('away_mode'))
|
||||
|
||||
def test_set_away_mode_on(self):
|
||||
"""Test setting the away mode on/true."""
|
||||
thermostat.set_away_mode(self.hass, True, ENTITY_NEST)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ENTITY_NEST)
|
||||
self.assertEqual('on', state.attributes.get('away_mode'))
|
||||
|
||||
def test_set_away_mode_off(self):
|
||||
"""Test setting the away mode off/false."""
|
||||
thermostat.set_away_mode(self.hass, False, ENTITY_NEST)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ENTITY_NEST)
|
||||
self.assertEqual('off', state.attributes.get('away_mode'))
|
||||
|
||||
def test_set_fan_mode_on_bad_attr(self):
|
||||
"""Test setting the fan mode on/true without required attribute."""
|
||||
state = self.hass.states.get(ENTITY_NEST)
|
||||
self.assertEqual('off', state.attributes.get('fan'))
|
||||
thermostat.set_fan_mode(self.hass, None, ENTITY_NEST)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ENTITY_NEST)
|
||||
self.assertEqual('off', state.attributes.get('fan'))
|
||||
|
||||
def test_set_fan_mode_on(self):
|
||||
"""Test setting the fan mode on/true."""
|
||||
thermostat.set_fan_mode(self.hass, True, ENTITY_NEST)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ENTITY_NEST)
|
||||
self.assertEqual('on', state.attributes.get('fan'))
|
||||
|
||||
def test_set_fan_mode_off(self):
|
||||
"""Test setting the fan mode off/false."""
|
||||
thermostat.set_fan_mode(self.hass, False, ENTITY_NEST)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ENTITY_NEST)
|
||||
self.assertEqual('off', state.attributes.get('fan'))
|
|
@ -1,5 +1,6 @@
|
|||
"""The tests for the heat control thermostat."""
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
|
@ -10,16 +11,55 @@ from homeassistant.const import (
|
|||
TEMP_CELCIUS,
|
||||
)
|
||||
from homeassistant.components import thermostat
|
||||
import homeassistant.components.thermostat.heat_control as heat_control
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
|
||||
entity = 'thermostat.test'
|
||||
ent_sensor = 'sensor.test'
|
||||
ent_switch = 'switch.test'
|
||||
min_temp = 3.0
|
||||
max_temp = 65.0
|
||||
target_temp = 42.0
|
||||
ENTITY = 'thermostat.test'
|
||||
ENT_SENSOR = 'sensor.test'
|
||||
ENT_SWITCH = 'switch.test'
|
||||
MIN_TEMP = 3.0
|
||||
MAX_TEMP = 65.0
|
||||
TARGET_TEMP = 42.0
|
||||
|
||||
|
||||
class TestSetupThermostatHeatControl(unittest.TestCase):
|
||||
"""Test the Heat Control thermostat with custom config."""
|
||||
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
"""Stop down everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_setup_missing_conf(self):
|
||||
"""Test set up heat_control with missing config values."""
|
||||
config = {
|
||||
'name': 'test',
|
||||
'target_sensor': ENT_SENSOR
|
||||
}
|
||||
add_devices = mock.MagicMock()
|
||||
result = heat_control.setup_platform(self.hass, config, add_devices)
|
||||
self.assertEqual(False, result)
|
||||
|
||||
def test_setup_with_sensor(self):
|
||||
"""Test set up heat_control with sensor to trigger update at init."""
|
||||
self.hass.states.set(ENT_SENSOR, 22.0, {
|
||||
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELCIUS
|
||||
})
|
||||
thermostat.setup(self.hass, {'thermostat': {
|
||||
'platform': 'heat_control',
|
||||
'name': 'test',
|
||||
'heater': ENT_SWITCH,
|
||||
'target_sensor': ENT_SENSOR
|
||||
}})
|
||||
state = self.hass.states.get(ENTITY)
|
||||
self.assertEqual(
|
||||
TEMP_CELCIUS, state.attributes.get('unit_of_measurement'))
|
||||
self.assertEqual(22.0, state.attributes.get('current_temperature'))
|
||||
|
||||
|
||||
class TestThermostatHeatControl(unittest.TestCase):
|
||||
|
@ -32,8 +72,8 @@ class TestThermostatHeatControl(unittest.TestCase):
|
|||
thermostat.setup(self.hass, {'thermostat': {
|
||||
'platform': 'heat_control',
|
||||
'name': 'test',
|
||||
'heater': ent_switch,
|
||||
'target_sensor': ent_sensor
|
||||
'heater': ENT_SWITCH,
|
||||
'target_sensor': ENT_SENSOR
|
||||
}})
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
|
@ -42,11 +82,11 @@ class TestThermostatHeatControl(unittest.TestCase):
|
|||
|
||||
def test_setup_defaults_to_unknown(self):
|
||||
"""Test the setting of defaults to unknown."""
|
||||
self.assertEqual('unknown', self.hass.states.get(entity).state)
|
||||
self.assertEqual('unknown', self.hass.states.get(ENTITY).state)
|
||||
|
||||
def test_default_setup_params(self):
|
||||
"""Test the setup with default parameters."""
|
||||
state = self.hass.states.get(entity)
|
||||
state = self.hass.states.get(ENTITY)
|
||||
self.assertEqual(7, state.attributes.get('min_temp'))
|
||||
self.assertEqual(35, state.attributes.get('max_temp'))
|
||||
self.assertEqual(None, state.attributes.get('temperature'))
|
||||
|
@ -56,25 +96,41 @@ class TestThermostatHeatControl(unittest.TestCase):
|
|||
thermostat.setup(self.hass, {'thermostat': {
|
||||
'platform': 'heat_control',
|
||||
'name': 'test',
|
||||
'heater': ent_switch,
|
||||
'target_sensor': ent_sensor,
|
||||
'min_temp': min_temp,
|
||||
'max_temp': max_temp,
|
||||
'target_temp': target_temp
|
||||
'heater': ENT_SWITCH,
|
||||
'target_sensor': ENT_SENSOR,
|
||||
'min_temp': MIN_TEMP,
|
||||
'max_temp': MAX_TEMP,
|
||||
'target_temp': TARGET_TEMP
|
||||
}})
|
||||
state = self.hass.states.get(entity)
|
||||
self.assertEqual(min_temp, state.attributes.get('min_temp'))
|
||||
self.assertEqual(max_temp, state.attributes.get('max_temp'))
|
||||
self.assertEqual(target_temp, state.attributes.get('temperature'))
|
||||
self.assertEqual(str(target_temp), self.hass.states.get(entity).state)
|
||||
state = self.hass.states.get(ENTITY)
|
||||
self.assertEqual(MIN_TEMP, state.attributes.get('min_temp'))
|
||||
self.assertEqual(MAX_TEMP, state.attributes.get('max_temp'))
|
||||
self.assertEqual(TARGET_TEMP, state.attributes.get('temperature'))
|
||||
self.assertEqual(str(TARGET_TEMP), self.hass.states.get(ENTITY).state)
|
||||
|
||||
def test_set_target_temp(self):
|
||||
"""Test the setting of the target temperature."""
|
||||
thermostat.set_temperature(self.hass, 30)
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertEqual('30.0', self.hass.states.get(entity).state)
|
||||
self.assertEqual('30.0', self.hass.states.get(ENTITY).state)
|
||||
|
||||
def test_set_target_temp_turns_on_heater(self):
|
||||
def test_sensor_bad_unit(self):
|
||||
"""Test sensor that have bad unit."""
|
||||
self._setup_sensor(22.0, unit='bad_unit')
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ENTITY)
|
||||
self.assertEqual(None, state.attributes.get('unit_of_measurement'))
|
||||
self.assertEqual(None, state.attributes.get('current_temperature'))
|
||||
|
||||
def test_sensor_bad_value(self):
|
||||
"""Test sensor that have None as state."""
|
||||
self._setup_sensor(None)
|
||||
self.hass.pool.block_till_done()
|
||||
state = self.hass.states.get(ENTITY)
|
||||
self.assertEqual(None, state.attributes.get('unit_of_measurement'))
|
||||
self.assertEqual(None, state.attributes.get('current_temperature'))
|
||||
|
||||
def test_set_target_temp_heater_on(self):
|
||||
"""Test if target temperature turn heater on."""
|
||||
self._setup_switch(False)
|
||||
self._setup_sensor(25)
|
||||
|
@ -85,9 +141,9 @@ class TestThermostatHeatControl(unittest.TestCase):
|
|||
call = self.calls[0]
|
||||
self.assertEqual('switch', call.domain)
|
||||
self.assertEqual(SERVICE_TURN_ON, call.service)
|
||||
self.assertEqual(ent_switch, call.data['entity_id'])
|
||||
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
|
||||
|
||||
def test_set_target_temp_turns_off_heater(self):
|
||||
def test_set_target_temp_heater_off(self):
|
||||
"""Test if target temperature turn heater off."""
|
||||
self._setup_switch(True)
|
||||
self._setup_sensor(30)
|
||||
|
@ -98,9 +154,9 @@ class TestThermostatHeatControl(unittest.TestCase):
|
|||
call = self.calls[0]
|
||||
self.assertEqual('switch', call.domain)
|
||||
self.assertEqual(SERVICE_TURN_OFF, call.service)
|
||||
self.assertEqual(ent_switch, call.data['entity_id'])
|
||||
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
|
||||
|
||||
def test_set_temp_change_turns_on_heater(self):
|
||||
def test_set_temp_change_heater_on(self):
|
||||
"""Test if temperature change turn heater on."""
|
||||
self._setup_switch(False)
|
||||
thermostat.set_temperature(self.hass, 30)
|
||||
|
@ -111,9 +167,9 @@ class TestThermostatHeatControl(unittest.TestCase):
|
|||
call = self.calls[0]
|
||||
self.assertEqual('switch', call.domain)
|
||||
self.assertEqual(SERVICE_TURN_ON, call.service)
|
||||
self.assertEqual(ent_switch, call.data['entity_id'])
|
||||
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
|
||||
|
||||
def test_temp_change_turns_off_heater(self):
|
||||
def test_temp_change_heater_off(self):
|
||||
"""Test if temperature change turn heater off."""
|
||||
self._setup_switch(True)
|
||||
thermostat.set_temperature(self.hass, 25)
|
||||
|
@ -124,17 +180,17 @@ class TestThermostatHeatControl(unittest.TestCase):
|
|||
call = self.calls[0]
|
||||
self.assertEqual('switch', call.domain)
|
||||
self.assertEqual(SERVICE_TURN_OFF, call.service)
|
||||
self.assertEqual(ent_switch, call.data['entity_id'])
|
||||
self.assertEqual(ENT_SWITCH, call.data['entity_id'])
|
||||
|
||||
def _setup_sensor(self, temp, unit=TEMP_CELCIUS):
|
||||
"""Setup the test sensor."""
|
||||
self.hass.states.set(ent_sensor, temp, {
|
||||
self.hass.states.set(ENT_SENSOR, temp, {
|
||||
ATTR_UNIT_OF_MEASUREMENT: unit
|
||||
})
|
||||
|
||||
def _setup_switch(self, is_on):
|
||||
"""Setup the test switch."""
|
||||
self.hass.states.set(ent_switch, STATE_ON if is_on else STATE_OFF)
|
||||
self.hass.states.set(ENT_SWITCH, STATE_ON if is_on else STATE_OFF)
|
||||
self.calls = []
|
||||
|
||||
def log_call(call):
|
||||
|
|
|
@ -23,6 +23,15 @@ class TestHoneywell(unittest.TestCase):
|
|||
CONF_PASSWORD: 'pass',
|
||||
'region': 'us',
|
||||
}
|
||||
bad_pass_config = {
|
||||
CONF_USERNAME: 'user',
|
||||
'region': 'us',
|
||||
}
|
||||
bad_region_config = {
|
||||
CONF_USERNAME: 'user',
|
||||
CONF_PASSWORD: 'pass',
|
||||
'region': 'un',
|
||||
}
|
||||
hass = mock.MagicMock()
|
||||
add_devices = mock.MagicMock()
|
||||
|
||||
|
@ -37,6 +46,10 @@ class TestHoneywell(unittest.TestCase):
|
|||
locations[0].devices_by_id.values.return_value = devices_1
|
||||
locations[1].devices_by_id.values.return_value = devices_2
|
||||
|
||||
result = honeywell.setup_platform(hass, bad_pass_config, add_devices)
|
||||
self.assertFalse(result)
|
||||
result = honeywell.setup_platform(hass, bad_region_config, add_devices)
|
||||
self.assertFalse(result)
|
||||
result = honeywell.setup_platform(hass, config, add_devices)
|
||||
self.assertTrue(result)
|
||||
mock_sc.assert_called_once_with('user', 'pass')
|
||||
|
|
Loading…
Reference in New Issue