core/tests/components/media_player/test_monoprice.py

476 lines
18 KiB
Python
Raw Normal View History

"""The tests for Monoprice Media player platform."""
import unittest
from unittest import mock
import voluptuous as vol
from collections import defaultdict
from homeassistant.components.media_player import (
DOMAIN, SUPPORT_TURN_ON, SUPPORT_TURN_OFF, SUPPORT_VOLUME_MUTE,
SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE)
from homeassistant.const import STATE_ON, STATE_OFF
import tests.common
from homeassistant.components.media_player.monoprice import (
DATA_MONOPRICE, PLATFORM_SCHEMA, SERVICE_SNAPSHOT,
SERVICE_RESTORE, setup_platform)
class AttrDict(dict):
"""Helper class for mocking attributes."""
def __setattr__(self, name, value):
"""Set attribute."""
self[name] = value
def __getattr__(self, item):
"""Get attribute."""
return self[item]
class MockMonoprice:
"""Mock for pymonoprice object."""
def __init__(self):
"""Init mock object."""
self.zones = defaultdict(lambda: AttrDict(power=True,
volume=0,
mute=True,
source=1))
def zone_status(self, zone_id):
"""Get zone status."""
status = self.zones[zone_id]
status.zone = zone_id
return AttrDict(status)
def set_source(self, zone_id, source_idx):
"""Set source for zone."""
self.zones[zone_id].source = source_idx
def set_power(self, zone_id, power):
"""Turn zone on/off."""
self.zones[zone_id].power = power
def set_mute(self, zone_id, mute):
"""Mute/unmute zone."""
self.zones[zone_id].mute = mute
def set_volume(self, zone_id, volume):
"""Set volume for zone."""
self.zones[zone_id].volume = volume
def restore_zone(self, zone):
"""Restore zone status."""
self.zones[zone.zone] = AttrDict(zone)
class TestMonopriceSchema(unittest.TestCase):
"""Test Monoprice schema."""
def test_valid_schema(self):
"""Test valid schema."""
valid_schema = {
'platform': 'monoprice',
'port': '/dev/ttyUSB0',
'zones': {11: {'name': 'a'},
12: {'name': 'a'},
13: {'name': 'a'},
14: {'name': 'a'},
15: {'name': 'a'},
16: {'name': 'a'},
21: {'name': 'a'},
22: {'name': 'a'},
23: {'name': 'a'},
24: {'name': 'a'},
25: {'name': 'a'},
26: {'name': 'a'},
31: {'name': 'a'},
32: {'name': 'a'},
33: {'name': 'a'},
34: {'name': 'a'},
35: {'name': 'a'},
36: {'name': 'a'},
},
'sources': {
1: {'name': 'a'},
2: {'name': 'a'},
3: {'name': 'a'},
4: {'name': 'a'},
5: {'name': 'a'},
6: {'name': 'a'}
}
}
PLATFORM_SCHEMA(valid_schema)
def test_invalid_schemas(self):
"""Test invalid schemas."""
schemas = (
{}, # Empty
None, # None
# Missing port
{
'platform': 'monoprice',
'name': 'Name',
'zones': {11: {'name': 'a'}},
'sources': {1: {'name': 'b'}},
},
# Invalid zone number
{
'platform': 'monoprice',
'port': 'aaa',
'name': 'Name',
'zones': {10: {'name': 'a'}},
'sources': {1: {'name': 'b'}},
},
# Invalid source number
{
'platform': 'monoprice',
'port': 'aaa',
'name': 'Name',
'zones': {11: {'name': 'a'}},
'sources': {0: {'name': 'b'}},
},
# Zone missing name
{
'platform': 'monoprice',
'port': 'aaa',
'name': 'Name',
'zones': {11: {}},
'sources': {1: {'name': 'b'}},
},
# Source missing name
{
'platform': 'monoprice',
'port': 'aaa',
'name': 'Name',
'zones': {11: {'name': 'a'}},
'sources': {1: {}},
},
)
for value in schemas:
with self.assertRaises(vol.MultipleInvalid):
PLATFORM_SCHEMA(value)
class TestMonopriceMediaPlayer(unittest.TestCase):
"""Test the media_player module."""
def setUp(self):
"""Set up the test case."""
self.monoprice = MockMonoprice()
self.hass = tests.common.get_test_home_assistant()
self.hass.start()
# Note, source dictionary is unsorted!
with mock.patch('pymonoprice.get_monoprice',
new=lambda *a: self.monoprice):
setup_platform(self.hass, {
'platform': 'monoprice',
'port': '/dev/ttyS0',
'name': 'Name',
'zones': {12: {'name': 'Zone name'}},
'sources': {1: {'name': 'one'},
3: {'name': 'three'},
2: {'name': 'two'}},
}, lambda *args, **kwargs: None, {})
self.hass.block_till_done()
self.media_player = self.hass.data[DATA_MONOPRICE][0]
self.media_player.hass = self.hass
self.media_player.entity_id = 'media_player.zone_1'
def tearDown(self):
"""Tear down the test case."""
self.hass.stop()
def test_setup_platform(self, *args):
"""Test setting up platform."""
# Two services must be registered
self.assertTrue(self.hass.services.has_service(DOMAIN,
SERVICE_RESTORE))
self.assertTrue(self.hass.services.has_service(DOMAIN,
SERVICE_SNAPSHOT))
self.assertEqual(len(self.hass.data[DATA_MONOPRICE]), 1)
self.assertEqual(self.hass.data[DATA_MONOPRICE][0].name, 'Zone name')
def test_service_calls_with_entity_id(self):
"""Test snapshot save/restore service calls."""
self.media_player.update()
self.assertEqual('Zone name', self.media_player.name)
self.assertEqual(STATE_ON, self.media_player.state)
self.assertEqual(0.0, self.media_player.volume_level, 0.0001)
self.assertTrue(self.media_player.is_volume_muted)
self.assertEqual('one', self.media_player.source)
# Saving default values
self.hass.services.call(DOMAIN, SERVICE_SNAPSHOT,
{'entity_id': 'media_player.zone_1'},
blocking=True)
# self.hass.block_till_done()
# Changing media player to new state
self.media_player.set_volume_level(1)
self.media_player.select_source('two')
self.media_player.mute_volume(False)
self.media_player.turn_off()
# Checking that values were indeed changed
self.media_player.update()
self.assertEqual('Zone name', self.media_player.name)
self.assertEqual(STATE_OFF, self.media_player.state)
self.assertEqual(1.0, self.media_player.volume_level, 0.0001)
self.assertFalse(self.media_player.is_volume_muted)
self.assertEqual('two', self.media_player.source)
# Restoring wrong media player to its previous state
# Nothing should be done
self.hass.services.call(DOMAIN, SERVICE_RESTORE,
{'entity_id': 'not_existing'},
blocking=True)
# self.hass.block_till_done()
# Checking that values were not (!) restored
self.media_player.update()
self.assertEqual('Zone name', self.media_player.name)
self.assertEqual(STATE_OFF, self.media_player.state)
self.assertEqual(1.0, self.media_player.volume_level, 0.0001)
self.assertFalse(self.media_player.is_volume_muted)
self.assertEqual('two', self.media_player.source)
# Restoring media player to its previous state
self.hass.services.call(DOMAIN, SERVICE_RESTORE,
{'entity_id': 'media_player.zone_1'},
blocking=True)
self.hass.block_till_done()
# Checking that values were restored
self.assertEqual('Zone name', self.media_player.name)
self.assertEqual(STATE_ON, self.media_player.state)
self.assertEqual(0.0, self.media_player.volume_level, 0.0001)
self.assertTrue(self.media_player.is_volume_muted)
self.assertEqual('one', self.media_player.source)
def test_service_calls_without_entity_id(self):
"""Test snapshot save/restore service calls."""
self.media_player.update()
self.assertEqual('Zone name', self.media_player.name)
self.assertEqual(STATE_ON, self.media_player.state)
self.assertEqual(0.0, self.media_player.volume_level, 0.0001)
self.assertTrue(self.media_player.is_volume_muted)
self.assertEqual('one', self.media_player.source)
# Restoring media player
# since there is no snapshot, nothing should be done
self.hass.services.call(DOMAIN, SERVICE_RESTORE, blocking=True)
self.hass.block_till_done()
self.media_player.update()
self.assertEqual('Zone name', self.media_player.name)
self.assertEqual(STATE_ON, self.media_player.state)
self.assertEqual(0.0, self.media_player.volume_level, 0.0001)
self.assertTrue(self.media_player.is_volume_muted)
self.assertEqual('one', self.media_player.source)
# Saving default values
self.hass.services.call(DOMAIN, SERVICE_SNAPSHOT, blocking=True)
self.hass.block_till_done()
# Changing media player to new state
self.media_player.set_volume_level(1)
self.media_player.select_source('two')
self.media_player.mute_volume(False)
self.media_player.turn_off()
# Checking that values were indeed changed
self.media_player.update()
self.assertEqual('Zone name', self.media_player.name)
self.assertEqual(STATE_OFF, self.media_player.state)
self.assertEqual(1.0, self.media_player.volume_level, 0.0001)
self.assertFalse(self.media_player.is_volume_muted)
self.assertEqual('two', self.media_player.source)
# Restoring media player to its previous state
self.hass.services.call(DOMAIN, SERVICE_RESTORE, blocking=True)
self.hass.block_till_done()
# Checking that values were restored
self.assertEqual('Zone name', self.media_player.name)
self.assertEqual(STATE_ON, self.media_player.state)
self.assertEqual(0.0, self.media_player.volume_level, 0.0001)
self.assertTrue(self.media_player.is_volume_muted)
self.assertEqual('one', self.media_player.source)
def test_update(self):
"""Test updating values from monoprice."""
self.assertIsNone(self.media_player.state)
self.assertIsNone(self.media_player.volume_level)
self.assertIsNone(self.media_player.is_volume_muted)
self.assertIsNone(self.media_player.source)
self.media_player.update()
self.assertEqual(STATE_ON, self.media_player.state)
self.assertEqual(0.0, self.media_player.volume_level, 0.0001)
self.assertTrue(self.media_player.is_volume_muted)
self.assertEqual('one', self.media_player.source)
def test_name(self):
"""Test name property."""
self.assertEqual('Zone name', self.media_player.name)
def test_state(self):
"""Test state property."""
self.assertIsNone(self.media_player.state)
self.media_player.update()
self.assertEqual(STATE_ON, self.media_player.state)
self.monoprice.zones[12].power = False
self.media_player.update()
self.assertEqual(STATE_OFF, self.media_player.state)
def test_volume_level(self):
"""Test volume level property."""
self.assertIsNone(self.media_player.volume_level)
self.media_player.update()
self.assertEqual(0.0, self.media_player.volume_level, 0.0001)
self.monoprice.zones[12].volume = 38
self.media_player.update()
self.assertEqual(1.0, self.media_player.volume_level, 0.0001)
self.monoprice.zones[12].volume = 19
self.media_player.update()
self.assertEqual(.5, self.media_player.volume_level, 0.0001)
def test_is_volume_muted(self):
"""Test volume muted property."""
self.assertIsNone(self.media_player.is_volume_muted)
self.media_player.update()
self.assertTrue(self.media_player.is_volume_muted)
self.monoprice.zones[12].mute = False
self.media_player.update()
self.assertFalse(self.media_player.is_volume_muted)
def test_supported_features(self):
"""Test supported features property."""
self.assertEqual(SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_SET |
SUPPORT_VOLUME_STEP | SUPPORT_TURN_ON |
SUPPORT_TURN_OFF | SUPPORT_SELECT_SOURCE,
self.media_player.supported_features)
def test_source(self):
"""Test source property."""
self.assertIsNone(self.media_player.source)
self.media_player.update()
self.assertEqual('one', self.media_player.source)
def test_media_title(self):
"""Test media title property."""
self.assertIsNone(self.media_player.media_title)
self.media_player.update()
self.assertEqual('one', self.media_player.media_title)
def test_source_list(self):
"""Test source list property."""
# Note, the list is sorted!
self.assertEqual(['one', 'two', 'three'],
self.media_player.source_list)
def test_select_source(self):
"""Test source selection methods."""
self.media_player.update()
self.assertEqual('one', self.media_player.source)
self.media_player.select_source('two')
self.assertEqual(2, self.monoprice.zones[12].source)
self.media_player.update()
self.assertEqual('two', self.media_player.source)
# Trying to set unknown source
self.media_player.select_source('no name')
self.assertEqual(2, self.monoprice.zones[12].source)
self.media_player.update()
self.assertEqual('two', self.media_player.source)
def test_turn_on(self):
"""Test turning on the zone."""
self.monoprice.zones[12].power = False
self.media_player.update()
self.assertEqual(STATE_OFF, self.media_player.state)
self.media_player.turn_on()
self.assertTrue(self.monoprice.zones[12].power)
self.media_player.update()
self.assertEqual(STATE_ON, self.media_player.state)
def test_turn_off(self):
"""Test turning off the zone."""
self.monoprice.zones[12].power = True
self.media_player.update()
self.assertEqual(STATE_ON, self.media_player.state)
self.media_player.turn_off()
self.assertFalse(self.monoprice.zones[12].power)
self.media_player.update()
self.assertEqual(STATE_OFF, self.media_player.state)
def test_mute_volume(self):
"""Test mute functionality."""
self.monoprice.zones[12].mute = True
self.media_player.update()
self.assertTrue(self.media_player.is_volume_muted)
self.media_player.mute_volume(False)
self.assertFalse(self.monoprice.zones[12].mute)
self.media_player.update()
self.assertFalse(self.media_player.is_volume_muted)
self.media_player.mute_volume(True)
self.assertTrue(self.monoprice.zones[12].mute)
self.media_player.update()
self.assertTrue(self.media_player.is_volume_muted)
def test_set_volume_level(self):
"""Test set volume level."""
self.media_player.set_volume_level(1.0)
self.assertEqual(38, self.monoprice.zones[12].volume)
self.assertTrue(isinstance(self.monoprice.zones[12].volume, int))
self.media_player.set_volume_level(0.0)
self.assertEqual(0, self.monoprice.zones[12].volume)
self.assertTrue(isinstance(self.monoprice.zones[12].volume, int))
self.media_player.set_volume_level(0.5)
self.assertEqual(19, self.monoprice.zones[12].volume)
self.assertTrue(isinstance(self.monoprice.zones[12].volume, int))
def test_volume_up(self):
"""Test increasing volume by one."""
self.monoprice.zones[12].volume = 37
self.media_player.update()
self.media_player.volume_up()
self.assertEqual(38, self.monoprice.zones[12].volume)
self.assertTrue(isinstance(self.monoprice.zones[12].volume, int))
# Try to raise value beyond max
self.media_player.update()
self.media_player.volume_up()
self.assertEqual(38, self.monoprice.zones[12].volume)
self.assertTrue(isinstance(self.monoprice.zones[12].volume, int))
def test_volume_down(self):
"""Test decreasing volume by one."""
self.monoprice.zones[12].volume = 1
self.media_player.update()
self.media_player.volume_down()
self.assertEqual(0, self.monoprice.zones[12].volume)
self.assertTrue(isinstance(self.monoprice.zones[12].volume, int))
# Try to lower value beyond minimum
self.media_player.update()
self.media_player.volume_down()
self.assertEqual(0, self.monoprice.zones[12].volume)
self.assertTrue(isinstance(self.monoprice.zones[12].volume, int))