Add initial test suite for arcam_fmj integration (#29335)

* Add initial tests

* Adjust test

* Typo
This commit is contained in:
Joakim Plate 2019-12-03 07:52:25 +01:00 committed by Paulus Schoutsen
parent 4191d9ca8d
commit 26b63e73ad
3 changed files with 428 additions and 32 deletions

View File

@ -0,0 +1,52 @@
"""Tests for the arcam_fmj component."""
from arcam.fmj.client import Client
from arcam.fmj.state import State
from asynctest import Mock
import pytest
from homeassistant.components.arcam_fmj import DEVICE_SCHEMA
from homeassistant.components.arcam_fmj.const import DOMAIN
from homeassistant.components.arcam_fmj.media_player import ArcamFmj
from homeassistant.const import CONF_HOST, CONF_PORT
MOCK_HOST = "127.0.0.1"
MOCK_PORT = 1234
MOCK_TURN_ON = {
"service": "switch.turn_on",
"data": {"entity_id": "switch.test"},
}
MOCK_NAME = "dummy"
MOCK_CONFIG = DEVICE_SCHEMA({CONF_HOST: MOCK_HOST, CONF_PORT: MOCK_PORT})
@pytest.fixture(name="config")
def config_fixture():
"""Create hass config fixture."""
return {DOMAIN: [{CONF_HOST: MOCK_HOST, CONF_PORT: MOCK_PORT}]}
@pytest.fixture(name="client")
def client_fixture():
"""Get a mocked client."""
client = Mock(Client)
client.host = MOCK_HOST
client.port = MOCK_PORT
return client
@pytest.fixture(name="state")
def state_fixture(client):
"""Get a mocked state."""
state = Mock(State)
state.client = client
state.zn = 1
state.get_power.return_value = True
return state
@pytest.fixture(name="player")
def player_fixture(hass, state):
"""Get standard player."""
player = ArcamFmj(state, MOCK_NAME, None)
player.async_schedule_update_ha_state = Mock()
return player

View File

@ -1,41 +1,37 @@
"""Tests for the Arcam FMJ config flow module."""
import pytest
from homeassistant import data_entry_flow
from homeassistant.const import CONF_HOST, CONF_PORT
from homeassistant.components.arcam_fmj.config_flow import ArcamFmjFlowHandler
from homeassistant.components.arcam_fmj.const import DOMAIN
from tests.common import MockConfigEntry, MockDependency
from .conftest import MOCK_CONFIG, MOCK_NAME
with MockDependency("arcam"), MockDependency("arcam.fmj"), MockDependency(
"arcam.fmj.client"
):
from homeassistant.components.arcam_fmj import DEVICE_SCHEMA
from homeassistant.components.arcam_fmj.config_flow import ArcamFmjFlowHandler
from homeassistant.components.arcam_fmj.const import DOMAIN
from tests.common import MockConfigEntry
MOCK_HOST = "127.0.0.1"
MOCK_PORT = 1234
MOCK_NAME = "Arcam FMJ"
MOCK_CONFIG = DEVICE_SCHEMA({CONF_HOST: MOCK_HOST, CONF_PORT: MOCK_PORT})
@pytest.fixture(name="config_entry")
def config_entry_fixture():
"""Create a mock HEOS config entry."""
return MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, title=MOCK_NAME)
@pytest.fixture(name="config_entry")
def config_entry_fixture():
"""Create a mock Arcam config entry."""
return MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, title=MOCK_NAME)
async def test_single_import_only(hass, config_entry):
"""Test form is shown when host not provided."""
config_entry.add_to_hass(hass)
flow = ArcamFmjFlowHandler()
flow.hass = hass
result = await flow.async_step_import(MOCK_CONFIG)
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_setup"
async def test_import(hass):
"""Test form is shown when host not provided."""
flow = ArcamFmjFlowHandler()
flow.hass = hass
result = await flow.async_step_import(MOCK_CONFIG)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["title"] == MOCK_NAME
assert result["data"] == MOCK_CONFIG
async def test_single_import_only(hass, config_entry):
"""Test form is shown when host not provided."""
config_entry.add_to_hass(hass)
flow = ArcamFmjFlowHandler()
flow.hass = hass
result = await flow.async_step_import(MOCK_CONFIG)
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "already_setup"
async def test_import(hass):
"""Test form is shown when host not provided."""
flow = ArcamFmjFlowHandler()
flow.hass = hass
result = await flow.async_step_import(MOCK_CONFIG)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["title"] == "Arcam FMJ"
assert result["data"] == MOCK_CONFIG

View File

@ -0,0 +1,348 @@
"""Tests for arcam fmj receivers."""
from math import isclose
from arcam.fmj import DecodeMode2CH, DecodeModeMCH, IncomingAudioFormat, SourceCodes
from asynctest.mock import ANY, MagicMock, Mock, PropertyMock, patch
import pytest
from homeassistant.components.arcam_fmj.const import (
DOMAIN,
SIGNAL_CLIENT_DATA,
SIGNAL_CLIENT_STARTED,
SIGNAL_CLIENT_STOPPED,
)
from homeassistant.components.arcam_fmj.media_player import ArcamFmj
from homeassistant.components.media_player.const import MEDIA_TYPE_MUSIC
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from .conftest import MOCK_HOST, MOCK_NAME, MOCK_PORT
MOCK_TURN_ON = {
"service": "switch.turn_on",
"data": {"entity_id": "switch.test"},
}
async def test_properties(player, state):
"""Test standard properties."""
assert player.unique_id is None
assert player.device_info == {
"identifiers": {(DOMAIN, MOCK_HOST, MOCK_PORT)},
"model": "FMJ",
"manufacturer": "Arcam",
}
assert not player.should_poll
async def test_powered_off(player, state):
"""Test properties in powered off state."""
state.get_source.return_value = None
state.get_power.return_value = None
assert player.source is None
assert player.state == STATE_OFF
async def test_powered_on(player, state):
"""Test properties in powered on state."""
state.get_source.return_value = SourceCodes.PVR
state.get_power.return_value = True
assert player.source == "PVR"
assert player.state == STATE_ON
async def test_supported_features_no_service(player, state):
"""Test support when turn on service exist."""
state.get_power.return_value = None
assert player.supported_features == 68876
state.get_power.return_value = False
assert player.supported_features == 69004
async def test_supported_features_service(hass, state):
"""Test support when turn on service exist."""
player = ArcamFmj(state, "dummy", MOCK_TURN_ON)
state.get_power.return_value = None
assert player.supported_features == 69004
state.get_power.return_value = False
assert player.supported_features == 69004
async def test_turn_on_without_service(player, state):
"""Test turn on service."""
state.get_power.return_value = None
await player.async_turn_on()
state.set_power.assert_not_called()
state.get_power.return_value = False
await player.async_turn_on()
state.set_power.assert_called_with(True)
async def test_turn_on_with_service(hass, state):
"""Test support when turn on service exist."""
player = ArcamFmj(state, "dummy", MOCK_TURN_ON)
player.hass = Mock(HomeAssistant)
with patch(
"homeassistant.components.arcam_fmj.media_player.async_call_from_config"
) as async_call_from_config:
state.get_power.return_value = None
await player.async_turn_on()
state.set_power.assert_not_called()
async_call_from_config.assert_called_with(
player.hass,
MOCK_TURN_ON,
variables=None,
blocking=True,
validate_config=False,
)
async def test_turn_off(player, state):
"""Test command to turn off."""
await player.async_turn_off()
state.set_power.assert_called_with(False)
@pytest.mark.parametrize("mute", [True, False])
async def test_mute_volume(player, state, mute):
"""Test mute functionallity."""
await player.async_mute_volume(mute)
state.set_mute.assert_called_with(mute)
player.async_schedule_update_ha_state.assert_called_with()
async def test_name(player):
"""Test name."""
assert player.name == MOCK_NAME
async def test_update(player, state):
"""Test update."""
await player.async_update()
state.update.assert_called_with()
@pytest.mark.parametrize(
"fmt, result",
[
(None, True),
(IncomingAudioFormat.PCM, True),
(IncomingAudioFormat.ANALOGUE_DIRECT, True),
(IncomingAudioFormat.DOLBY_DIGITAL, False),
],
)
async def test_2ch(player, state, fmt, result):
"""Test selection of 2ch mode."""
state.get_incoming_audio_format.return_value = (fmt, None)
assert player._get_2ch() == result # pylint: disable=W0212
@pytest.mark.parametrize(
"source, value",
[("PVR", SourceCodes.PVR), ("BD", SourceCodes.BD), ("INVALID", None)],
)
async def test_select_source(player, state, source, value):
"""Test selection of source."""
await player.async_select_source(source)
if value:
state.set_source.assert_called_with(value)
else:
state.set_source.assert_not_called()
async def test_source_list(player, state):
"""Test source list."""
state.get_source_list.return_value = [SourceCodes.BD]
assert player.source_list == ["BD"]
@pytest.mark.parametrize(
"mode, mode_sel, mode_2ch, mode_mch",
[
("STEREO", True, DecodeMode2CH.STEREO, None),
("STEREO", False, None, None),
("STEREO", False, None, None),
],
)
async def test_select_sound_mode(player, state, mode, mode_sel, mode_2ch, mode_mch):
"""Test selection sound mode."""
player._get_2ch = Mock(return_value=mode_sel) # pylint: disable=W0212
await player.async_select_sound_mode(mode)
if mode_2ch:
state.set_decode_mode_2ch.assert_called_with(mode_2ch)
else:
state.set_decode_mode_2ch.assert_not_called()
if mode_mch:
state.set_decode_mode_mch.assert_called_with(mode_mch)
else:
state.set_decode_mode_mch.assert_not_called()
async def test_volume_up(player, state):
"""Test mute functionallity."""
await player.async_volume_up()
state.inc_volume.assert_called_with()
player.async_schedule_update_ha_state.assert_called_with()
async def test_volume_down(player, state):
"""Test mute functionallity."""
await player.async_volume_down()
state.dec_volume.assert_called_with()
player.async_schedule_update_ha_state.assert_called_with()
@pytest.mark.parametrize(
"mode, mode_sel, mode_2ch, mode_mch",
[
("STEREO", True, DecodeMode2CH.STEREO, None),
("STEREO_DOWNMIX", False, None, DecodeModeMCH.STEREO_DOWNMIX),
(None, False, None, None),
],
)
async def test_sound_mode(player, state, mode, mode_sel, mode_2ch, mode_mch):
"""Test selection sound mode."""
player._get_2ch = Mock(return_value=mode_sel) # pylint: disable=W0212
state.get_decode_mode_2ch.return_value = mode_2ch
state.get_decode_mode_mch.return_value = mode_mch
assert player.sound_mode == mode
async def test_sound_mode_list(player, state):
"""Test sound mode list."""
player._get_2ch = Mock(return_value=True) # pylint: disable=W0212
assert sorted(player.sound_mode_list) == sorted([x.name for x in DecodeMode2CH])
player._get_2ch = Mock(return_value=False) # pylint: disable=W0212
assert sorted(player.sound_mode_list) == sorted([x.name for x in DecodeModeMCH])
async def test_sound_mode_zone_x(player, state):
"""Test second zone sound mode."""
state.zn = 2
assert player.sound_mode is None
assert player.sound_mode_list is None
async def test_is_volume_muted(player, state):
"""Test muted."""
state.get_mute.return_value = True
assert player.is_volume_muted is True # pylint: disable=singleton-comparison
state.get_mute.return_value = False
assert player.is_volume_muted is False # pylint: disable=singleton-comparison
state.get_mute.return_value = None
assert player.is_volume_muted is None
async def test_volume_level(player, state):
"""Test volume."""
state.get_volume.return_value = 0
assert isclose(player.volume_level, 0.0)
state.get_volume.return_value = 50
assert isclose(player.volume_level, 50.0 / 99)
state.get_volume.return_value = 99
assert isclose(player.volume_level, 1.0)
state.get_volume.return_value = None
assert player.volume_level is None
@pytest.mark.parametrize("volume, call", [(0.0, 0), (0.5, 50), (1.0, 99)])
async def test_set_volume_level(player, state, volume, call):
"""Test setting volume."""
await player.async_set_volume_level(volume)
state.set_volume.assert_called_with(call)
@pytest.mark.parametrize(
"source, media_content_type",
[
(SourceCodes.DAB, MEDIA_TYPE_MUSIC),
(SourceCodes.FM, MEDIA_TYPE_MUSIC),
(SourceCodes.PVR, None),
(None, None),
],
)
async def test_media_content_type(player, state, source, media_content_type):
"""Test content type deduction."""
state.get_source.return_value = source
assert player.media_content_type == media_content_type
@pytest.mark.parametrize(
"source, dab, rds, channel",
[
(SourceCodes.DAB, "dab", "rds", "dab"),
(SourceCodes.DAB, None, None, None),
(SourceCodes.FM, "dab", "rds", "rds"),
(SourceCodes.FM, None, None, None),
(SourceCodes.PVR, "dab", "rds", None),
],
)
async def test_media_channel(player, state, source, dab, rds, channel):
"""Test media channel."""
state.get_dab_station.return_value = dab
state.get_rds_information.return_value = rds
state.get_source.return_value = source
assert player.media_channel == channel
@pytest.mark.parametrize(
"source, dls, artist",
[
(SourceCodes.DAB, "dls", "dls"),
(SourceCodes.FM, "dls", None),
(SourceCodes.DAB, None, None),
],
)
async def test_media_artist(player, state, source, dls, artist):
"""Test media artist."""
state.get_dls_pdt.return_value = dls
state.get_source.return_value = source
assert player.media_artist == artist
@pytest.mark.parametrize(
"source, channel, title",
[
(SourceCodes.DAB, "channel", "DAB - channel"),
(SourceCodes.DAB, None, "DAB"),
(None, None, None),
],
)
async def test_media_title(player, state, source, channel, title):
"""Test media title."""
state.get_source.return_value = source
with patch.object(
ArcamFmj, "media_channel", new_callable=PropertyMock
) as media_channel:
media_channel.return_value = channel
assert player.media_title == title
async def test_added_to_hass(player, state):
"""Test addition to hass."""
connectors = {}
def _connect(signal, fun):
connectors[signal] = fun
player.hass = MagicMock()
player.hass.helpers.dispatcher.async_dispatcher_connect.side_effects = _connect
await player.async_added_to_hass()
state.start.assert_called_with()
player.hass.helpers.dispatcher.async_dispatcher_connect.assert_any_call(
SIGNAL_CLIENT_DATA, ANY
)
player.hass.helpers.dispatcher.async_dispatcher_connect.assert_any_call(
SIGNAL_CLIENT_STARTED, ANY
)
player.hass.helpers.dispatcher.async_dispatcher_connect.assert_any_call(
SIGNAL_CLIENT_STOPPED, ANY
)