370 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			370 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
"""Test the pjlink media player platform."""
 | 
						|
from datetime import timedelta
 | 
						|
import socket
 | 
						|
from unittest.mock import create_autospec, patch
 | 
						|
 | 
						|
import pypjlink
 | 
						|
from pypjlink import MUTE_AUDIO
 | 
						|
from pypjlink.projector import ProjectorError
 | 
						|
import pytest
 | 
						|
 | 
						|
import homeassistant.components.media_player as media_player
 | 
						|
from homeassistant.const import ATTR_ENTITY_ID
 | 
						|
from homeassistant.core import HomeAssistant
 | 
						|
from homeassistant.setup import async_setup_component
 | 
						|
from homeassistant.util import dt as dt_util
 | 
						|
 | 
						|
from tests.common import assert_setup_component, async_fire_time_changed
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture(name="projector_from_address")
 | 
						|
def projector_from_address():
 | 
						|
    """Create pjlink Projector mock."""
 | 
						|
 | 
						|
    with patch("pypjlink.Projector.from_address") as from_address:
 | 
						|
        constructor = create_autospec(pypjlink.Projector)
 | 
						|
        from_address.return_value = constructor.return_value
 | 
						|
        yield from_address
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture(name="mocked_projector")
 | 
						|
def mocked_projector(projector_from_address):
 | 
						|
    """Create pjlink Projector instance mock."""
 | 
						|
 | 
						|
    instance = projector_from_address.return_value
 | 
						|
 | 
						|
    with instance as mocked_instance:
 | 
						|
        mocked_instance.get_name.return_value = "Test"
 | 
						|
        mocked_instance.get_power.return_value = "on"
 | 
						|
        mocked_instance.get_mute.return_value = [0, True]
 | 
						|
        mocked_instance.get_input.return_value = [0, 1]
 | 
						|
        mocked_instance.get_inputs.return_value = (
 | 
						|
            ("HDMI", 1),
 | 
						|
            ("HDMI", 2),
 | 
						|
            ("VGA", 1),
 | 
						|
        )
 | 
						|
 | 
						|
        yield mocked_instance
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize("side_effect", [socket.timeout, OSError])
 | 
						|
async def test_offline_initialization(
 | 
						|
    projector_from_address, hass: HomeAssistant, side_effect
 | 
						|
) -> None:
 | 
						|
    """Test initialization of a device that is offline."""
 | 
						|
 | 
						|
    with assert_setup_component(1, media_player.DOMAIN):
 | 
						|
        projector_from_address.side_effect = side_effect
 | 
						|
 | 
						|
        assert await async_setup_component(
 | 
						|
            hass,
 | 
						|
            media_player.DOMAIN,
 | 
						|
            {
 | 
						|
                media_player.DOMAIN: {
 | 
						|
                    "platform": "pjlink",
 | 
						|
                    "name": "test_offline",
 | 
						|
                    "host": "127.0.0.1",
 | 
						|
                }
 | 
						|
            },
 | 
						|
        )
 | 
						|
        await hass.async_block_till_done()
 | 
						|
 | 
						|
        state = hass.states.get("media_player.test_offline")
 | 
						|
        assert state.state == "unavailable"
 | 
						|
 | 
						|
 | 
						|
async def test_initialization(projector_from_address, hass: HomeAssistant) -> None:
 | 
						|
    """Test a device that is available."""
 | 
						|
 | 
						|
    with assert_setup_component(1, media_player.DOMAIN):
 | 
						|
        instance = projector_from_address.return_value
 | 
						|
 | 
						|
        with instance as mocked_instance:
 | 
						|
            mocked_instance.get_name.return_value = "Test"
 | 
						|
            mocked_instance.get_inputs.return_value = (
 | 
						|
                ("HDMI", 1),
 | 
						|
                ("HDMI", 2),
 | 
						|
                ("VGA", 1),
 | 
						|
            )
 | 
						|
 | 
						|
        assert await async_setup_component(
 | 
						|
            hass,
 | 
						|
            media_player.DOMAIN,
 | 
						|
            {
 | 
						|
                media_player.DOMAIN: {
 | 
						|
                    "platform": "pjlink",
 | 
						|
                    "host": "127.0.0.1",
 | 
						|
                }
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        await hass.async_block_till_done()
 | 
						|
 | 
						|
        state = hass.states.get("media_player.test")
 | 
						|
        assert state.state == "off"
 | 
						|
 | 
						|
        assert "source_list" in state.attributes
 | 
						|
        source_list = state.attributes["source_list"]
 | 
						|
 | 
						|
        assert set(source_list) == {"HDMI 1", "HDMI 2", "VGA 1"}
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize("power_state", ["on", "warm-up"])
 | 
						|
async def test_on_state_init(
 | 
						|
    projector_from_address, hass: HomeAssistant, power_state
 | 
						|
) -> None:
 | 
						|
    """Test a device that is available."""
 | 
						|
 | 
						|
    with assert_setup_component(1, media_player.DOMAIN):
 | 
						|
        instance = projector_from_address.return_value
 | 
						|
 | 
						|
        with instance as mocked_instance:
 | 
						|
            mocked_instance.get_name.return_value = "Test"
 | 
						|
            mocked_instance.get_power.return_value = power_state
 | 
						|
            mocked_instance.get_inputs.return_value = (("HDMI", 1),)
 | 
						|
            mocked_instance.get_input.return_value = ("HDMI", 1)
 | 
						|
 | 
						|
        assert await async_setup_component(
 | 
						|
            hass,
 | 
						|
            media_player.DOMAIN,
 | 
						|
            {
 | 
						|
                media_player.DOMAIN: {
 | 
						|
                    "platform": "pjlink",
 | 
						|
                    "host": "127.0.0.1",
 | 
						|
                }
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        await hass.async_block_till_done()
 | 
						|
 | 
						|
        state = hass.states.get("media_player.test")
 | 
						|
        assert state.state == "on"
 | 
						|
 | 
						|
        assert state.attributes["source"] == "HDMI 1"
 | 
						|
 | 
						|
 | 
						|
async def test_api_error(projector_from_address, hass: HomeAssistant) -> None:
 | 
						|
    """Test invalid api responses."""
 | 
						|
 | 
						|
    with assert_setup_component(1, media_player.DOMAIN):
 | 
						|
        instance = projector_from_address.return_value
 | 
						|
 | 
						|
        with instance as mocked_instance:
 | 
						|
            mocked_instance.get_name.return_value = "Test"
 | 
						|
            mocked_instance.get_inputs.return_value = (
 | 
						|
                ("HDMI", 1),
 | 
						|
                ("HDMI", 2),
 | 
						|
                ("VGA", 1),
 | 
						|
            )
 | 
						|
            mocked_instance.get_power.side_effect = KeyError("OK")
 | 
						|
 | 
						|
        assert await async_setup_component(
 | 
						|
            hass,
 | 
						|
            media_player.DOMAIN,
 | 
						|
            {
 | 
						|
                media_player.DOMAIN: {
 | 
						|
                    "platform": "pjlink",
 | 
						|
                    "host": "127.0.0.1",
 | 
						|
                }
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        await hass.async_block_till_done()
 | 
						|
 | 
						|
        state = hass.states.get("media_player.test")
 | 
						|
        assert state.state == "off"
 | 
						|
 | 
						|
 | 
						|
async def test_update_unavailable(projector_from_address, hass: HomeAssistant) -> None:
 | 
						|
    """Test update to a device that is unavailable."""
 | 
						|
 | 
						|
    with assert_setup_component(1, media_player.DOMAIN):
 | 
						|
        instance = projector_from_address.return_value
 | 
						|
 | 
						|
        with instance as mocked_instance:
 | 
						|
            mocked_instance.get_name.return_value = "Test"
 | 
						|
            mocked_instance.get_inputs.return_value = (
 | 
						|
                ("HDMI", 1),
 | 
						|
                ("HDMI", 2),
 | 
						|
                ("VGA", 1),
 | 
						|
            )
 | 
						|
 | 
						|
        assert await async_setup_component(
 | 
						|
            hass,
 | 
						|
            media_player.DOMAIN,
 | 
						|
            {
 | 
						|
                media_player.DOMAIN: {
 | 
						|
                    "platform": "pjlink",
 | 
						|
                    "host": "127.0.0.1",
 | 
						|
                }
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        await hass.async_block_till_done()
 | 
						|
 | 
						|
        state = hass.states.get("media_player.test")
 | 
						|
        assert state.state == "off"
 | 
						|
 | 
						|
        projector_from_address.side_effect = socket.timeout
 | 
						|
        async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
 | 
						|
        await hass.async_block_till_done()
 | 
						|
 | 
						|
        state = hass.states.get("media_player.test")
 | 
						|
        assert state.state == "unavailable"
 | 
						|
 | 
						|
 | 
						|
async def test_unavailable_time(mocked_projector, hass: HomeAssistant) -> None:
 | 
						|
    """Test unavailable time projector error."""
 | 
						|
 | 
						|
    assert await async_setup_component(
 | 
						|
        hass,
 | 
						|
        media_player.DOMAIN,
 | 
						|
        {
 | 
						|
            media_player.DOMAIN: {
 | 
						|
                "platform": "pjlink",
 | 
						|
                "host": "127.0.0.1",
 | 
						|
            }
 | 
						|
        },
 | 
						|
    )
 | 
						|
 | 
						|
    await hass.async_block_till_done()
 | 
						|
 | 
						|
    state = hass.states.get("media_player.test")
 | 
						|
    assert state.state == "on"
 | 
						|
    assert state.attributes["source"] is not None
 | 
						|
    assert state.attributes["is_volume_muted"] is not False
 | 
						|
 | 
						|
    mocked_projector.get_power.side_effect = ProjectorError("unavailable time")
 | 
						|
    async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
 | 
						|
    await hass.async_block_till_done()
 | 
						|
 | 
						|
    state = hass.states.get("media_player.test")
 | 
						|
    assert state.state == "off"
 | 
						|
    assert "source" not in state.attributes
 | 
						|
    assert "is_volume_muted" not in state.attributes
 | 
						|
 | 
						|
 | 
						|
async def test_turn_off(mocked_projector, hass: HomeAssistant) -> None:
 | 
						|
    """Test turning off beamer."""
 | 
						|
 | 
						|
    assert await async_setup_component(
 | 
						|
        hass,
 | 
						|
        media_player.DOMAIN,
 | 
						|
        {
 | 
						|
            media_player.DOMAIN: {
 | 
						|
                "platform": "pjlink",
 | 
						|
                "host": "127.0.0.1",
 | 
						|
            }
 | 
						|
        },
 | 
						|
    )
 | 
						|
 | 
						|
    await hass.async_block_till_done()
 | 
						|
    await hass.services.async_call(
 | 
						|
        domain=media_player.DOMAIN,
 | 
						|
        service="turn_off",
 | 
						|
        service_data={ATTR_ENTITY_ID: "media_player.test"},
 | 
						|
        blocking=True,
 | 
						|
    )
 | 
						|
 | 
						|
    mocked_projector.set_power.assert_called_with("off")
 | 
						|
 | 
						|
 | 
						|
async def test_turn_on(mocked_projector, hass: HomeAssistant) -> None:
 | 
						|
    """Test turning on beamer."""
 | 
						|
 | 
						|
    assert await async_setup_component(
 | 
						|
        hass,
 | 
						|
        media_player.DOMAIN,
 | 
						|
        {
 | 
						|
            media_player.DOMAIN: {
 | 
						|
                "platform": "pjlink",
 | 
						|
                "host": "127.0.0.1",
 | 
						|
            }
 | 
						|
        },
 | 
						|
    )
 | 
						|
 | 
						|
    await hass.async_block_till_done()
 | 
						|
    await hass.services.async_call(
 | 
						|
        domain=media_player.DOMAIN,
 | 
						|
        service="turn_on",
 | 
						|
        service_data={ATTR_ENTITY_ID: "media_player.test"},
 | 
						|
        blocking=True,
 | 
						|
    )
 | 
						|
 | 
						|
    mocked_projector.set_power.assert_called_with("on")
 | 
						|
 | 
						|
 | 
						|
async def test_mute(mocked_projector, hass: HomeAssistant) -> None:
 | 
						|
    """Test muting beamer."""
 | 
						|
 | 
						|
    assert await async_setup_component(
 | 
						|
        hass,
 | 
						|
        media_player.DOMAIN,
 | 
						|
        {
 | 
						|
            media_player.DOMAIN: {
 | 
						|
                "platform": "pjlink",
 | 
						|
                "host": "127.0.0.1",
 | 
						|
            }
 | 
						|
        },
 | 
						|
    )
 | 
						|
 | 
						|
    await hass.async_block_till_done()
 | 
						|
    await hass.services.async_call(
 | 
						|
        domain=media_player.DOMAIN,
 | 
						|
        service="volume_mute",
 | 
						|
        service_data={ATTR_ENTITY_ID: "media_player.test", "is_volume_muted": True},
 | 
						|
        blocking=True,
 | 
						|
    )
 | 
						|
 | 
						|
    mocked_projector.set_mute.assert_called_with(MUTE_AUDIO, True)
 | 
						|
 | 
						|
 | 
						|
async def test_unmute(mocked_projector, hass: HomeAssistant) -> None:
 | 
						|
    """Test unmuting beamer."""
 | 
						|
 | 
						|
    assert await async_setup_component(
 | 
						|
        hass,
 | 
						|
        media_player.DOMAIN,
 | 
						|
        {
 | 
						|
            media_player.DOMAIN: {
 | 
						|
                "platform": "pjlink",
 | 
						|
                "host": "127.0.0.1",
 | 
						|
            }
 | 
						|
        },
 | 
						|
    )
 | 
						|
 | 
						|
    await hass.async_block_till_done()
 | 
						|
    await hass.services.async_call(
 | 
						|
        domain=media_player.DOMAIN,
 | 
						|
        service="volume_mute",
 | 
						|
        service_data={ATTR_ENTITY_ID: "media_player.test", "is_volume_muted": False},
 | 
						|
        blocking=True,
 | 
						|
    )
 | 
						|
 | 
						|
    mocked_projector.set_mute.assert_called_with(MUTE_AUDIO, False)
 | 
						|
 | 
						|
 | 
						|
async def test_select_source(mocked_projector, hass: HomeAssistant) -> None:
 | 
						|
    """Test selecting source."""
 | 
						|
 | 
						|
    assert await async_setup_component(
 | 
						|
        hass,
 | 
						|
        media_player.DOMAIN,
 | 
						|
        {
 | 
						|
            media_player.DOMAIN: {
 | 
						|
                "platform": "pjlink",
 | 
						|
                "host": "127.0.0.1",
 | 
						|
            }
 | 
						|
        },
 | 
						|
    )
 | 
						|
 | 
						|
    await hass.async_block_till_done()
 | 
						|
    await hass.services.async_call(
 | 
						|
        domain=media_player.DOMAIN,
 | 
						|
        service="select_source",
 | 
						|
        service_data={ATTR_ENTITY_ID: "media_player.test", "source": "VGA 1"},
 | 
						|
        blocking=True,
 | 
						|
    )
 | 
						|
 | 
						|
    mocked_projector.set_input.assert_called_with("VGA", 1)
 |