parent
ac594e6bce
commit
7390e3a997
9 changed files with 290 additions and 242 deletions
|
@ -1,20 +1,8 @@
|
|||
"""Tests for the IPP integration."""
|
||||
import aiohttp
|
||||
from pyipp import IPPConnectionUpgradeRequired, IPPError
|
||||
|
||||
from homeassistant.components import zeroconf
|
||||
from homeassistant.components.ipp.const import CONF_BASE_PATH, DOMAIN
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_PORT,
|
||||
CONF_SSL,
|
||||
CONF_UUID,
|
||||
CONF_VERIFY_SSL,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry, get_fixture_path
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
from homeassistant.components.ipp.const import CONF_BASE_PATH
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_SSL, CONF_VERIFY_SSL
|
||||
|
||||
ATTR_HOSTNAME = "hostname"
|
||||
ATTR_PROPERTIES = "properties"
|
||||
|
@ -59,99 +47,3 @@ MOCK_ZEROCONF_IPPS_SERVICE_INFO = zeroconf.ZeroconfServiceInfo(
|
|||
port=ZEROCONF_PORT,
|
||||
properties={"rp": ZEROCONF_RP},
|
||||
)
|
||||
|
||||
|
||||
def load_fixture_binary(filename):
|
||||
"""Load a binary fixture."""
|
||||
return get_fixture_path(filename, "ipp").read_bytes()
|
||||
|
||||
|
||||
def mock_connection(
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
host: str = HOST,
|
||||
port: int = PORT,
|
||||
ssl: bool = False,
|
||||
base_path: str = BASE_PATH,
|
||||
conn_error: bool = False,
|
||||
conn_upgrade_error: bool = False,
|
||||
ipp_error: bool = False,
|
||||
no_unique_id: bool = False,
|
||||
parse_error: bool = False,
|
||||
version_not_supported: bool = False,
|
||||
):
|
||||
"""Mock the IPP connection."""
|
||||
scheme = "https" if ssl else "http"
|
||||
ipp_url = f"{scheme}://{host}:{port}"
|
||||
|
||||
if ipp_error:
|
||||
aioclient_mock.post(f"{ipp_url}{base_path}", exc=IPPError)
|
||||
return
|
||||
|
||||
if conn_error:
|
||||
aioclient_mock.post(f"{ipp_url}{base_path}", exc=aiohttp.ClientError)
|
||||
return
|
||||
|
||||
if conn_upgrade_error:
|
||||
aioclient_mock.post(f"{ipp_url}{base_path}", exc=IPPConnectionUpgradeRequired)
|
||||
return
|
||||
|
||||
fixture = "get-printer-attributes.bin"
|
||||
if no_unique_id:
|
||||
fixture = "get-printer-attributes-success-nodata.bin"
|
||||
elif version_not_supported:
|
||||
fixture = "get-printer-attributes-error-0x0503.bin"
|
||||
|
||||
if parse_error:
|
||||
content = "BAD"
|
||||
else:
|
||||
content = load_fixture_binary(fixture)
|
||||
|
||||
aioclient_mock.post(
|
||||
f"{ipp_url}{base_path}",
|
||||
content=content,
|
||||
headers={"Content-Type": "application/ipp"},
|
||||
)
|
||||
|
||||
|
||||
async def init_integration(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
skip_setup: bool = False,
|
||||
host: str = HOST,
|
||||
port: int = PORT,
|
||||
ssl: bool = False,
|
||||
base_path: str = BASE_PATH,
|
||||
uuid: str = "cfe92100-67c4-11d4-a45f-f8d027761251",
|
||||
unique_id: str = "cfe92100-67c4-11d4-a45f-f8d027761251",
|
||||
conn_error: bool = False,
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the IPP integration in Home Assistant."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id=unique_id,
|
||||
data={
|
||||
CONF_HOST: host,
|
||||
CONF_PORT: port,
|
||||
CONF_SSL: ssl,
|
||||
CONF_VERIFY_SSL: True,
|
||||
CONF_BASE_PATH: base_path,
|
||||
CONF_UUID: uuid,
|
||||
},
|
||||
)
|
||||
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
mock_connection(
|
||||
aioclient_mock,
|
||||
host=host,
|
||||
port=port,
|
||||
ssl=ssl,
|
||||
base_path=base_path,
|
||||
conn_error=conn_error,
|
||||
)
|
||||
|
||||
if not skip_setup:
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return entry
|
||||
|
|
99
tests/components/ipp/conftest.py
Normal file
99
tests/components/ipp/conftest.py
Normal file
|
@ -0,0 +1,99 @@
|
|||
"""Fixtures for IPP integration tests."""
|
||||
from collections.abc import Generator
|
||||
import json
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from pyipp import Printer
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.ipp.const import CONF_BASE_PATH, DOMAIN
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_PORT,
|
||||
CONF_SSL,
|
||||
CONF_UUID,
|
||||
CONF_VERIFY_SSL,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry, load_fixture
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry() -> MockConfigEntry:
|
||||
"""Return the default mocked config entry."""
|
||||
return MockConfigEntry(
|
||||
title="IPP Printer",
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
CONF_HOST: "192.168.1.31",
|
||||
CONF_PORT: 631,
|
||||
CONF_SSL: False,
|
||||
CONF_VERIFY_SSL: True,
|
||||
CONF_BASE_PATH: "/ipp/print",
|
||||
CONF_UUID: "cfe92100-67c4-11d4-a45f-f8d027761251",
|
||||
},
|
||||
unique_id="cfe92100-67c4-11d4-a45f-f8d027761251",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_setup_entry() -> Generator[AsyncMock, None, None]:
|
||||
"""Mock setting up a config entry."""
|
||||
with patch(
|
||||
"homeassistant.components.ipp.async_setup_entry", return_value=True
|
||||
) as mock_setup_entry:
|
||||
yield mock_setup_entry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def mock_printer(
|
||||
request: pytest.FixtureRequest,
|
||||
) -> Printer:
|
||||
"""Return the mocked printer."""
|
||||
fixture: str = "ipp/printer.json"
|
||||
if hasattr(request, "param") and request.param:
|
||||
fixture = request.param
|
||||
|
||||
return Printer.from_dict(json.loads(load_fixture(fixture)))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_ipp_config_flow(
|
||||
mock_printer: Printer,
|
||||
) -> Generator[None, MagicMock, None]:
|
||||
"""Return a mocked IPP client."""
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ipp.config_flow.IPP", autospec=True
|
||||
) as ipp_mock:
|
||||
client = ipp_mock.return_value
|
||||
client.printer.return_value = mock_printer
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_ipp(
|
||||
request: pytest.FixtureRequest, mock_printer: Printer
|
||||
) -> Generator[None, MagicMock, None]:
|
||||
"""Return a mocked IPP client."""
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.ipp.coordinator.IPP", autospec=True
|
||||
) as ipp_mock:
|
||||
client = ipp_mock.return_value
|
||||
client.printer.return_value = mock_printer
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def init_integration(
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_ipp: MagicMock
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the IPP integration for testing."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return mock_config_entry
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
36
tests/components/ipp/fixtures/printer.json
Normal file
36
tests/components/ipp/fixtures/printer.json
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"printer-uuid": "urn:uuid:cfe92100-67c4-11d4-a45f-f8d027761251",
|
||||
"printer-state": "idle",
|
||||
"printer-name": "Test Printer",
|
||||
"printer-location": null,
|
||||
"printer-make-and-model": "Test HA-1000 Series",
|
||||
"printer-device-id": "MFG:TEST;CMD:ESCPL2,BDC,D4,D4PX,ESCPR7,END4,GENEP,URF;MDL:HA-1000 Series;CLS:PRINTER;DES:TEST HA-1000 Series;CID:EpsonRGB;FID:FXN,DPA,WFA,ETN,AFN,DAN,WRA;RID:20;DDS:022500;ELG:1000;SN:555534593035345555;URF:CP1,PQ4-5,OB9,OFU0,RS360,SRGB24,W8,DM3,IS1-7-6,V1.4,MT1-3-7-8-10-11-12;",
|
||||
"printer-uri-supported": [
|
||||
"ipps://192.168.1.31:631/ipp/print",
|
||||
"ipp://192.168.1.31:631/ipp/print"
|
||||
],
|
||||
"uri-authentication-supported": ["none", "none"],
|
||||
"uri-security-supported": ["tls", "none"],
|
||||
"printer-info": "Test HA-1000 Series",
|
||||
"printer-up-time": 30,
|
||||
"printer-firmware-string-version": "20.23.06HA",
|
||||
"printer-more-info": "http://192.168.1.31:80/PRESENTATION/BONJOUR",
|
||||
"marker-names": [
|
||||
"Black ink",
|
||||
"Photo black ink",
|
||||
"Cyan ink",
|
||||
"Yellow ink",
|
||||
"Magenta ink"
|
||||
],
|
||||
"marker-types": [
|
||||
"ink-cartridge",
|
||||
"ink-cartridge",
|
||||
"ink-cartridge",
|
||||
"ink-cartridge",
|
||||
"ink-cartridge"
|
||||
],
|
||||
"marker-colors": ["#000000", "#000000", "#00FFFF", "#FFFF00", "#FF00FF"],
|
||||
"marker-levels": [58, 98, 91, 95, 73],
|
||||
"marker-low-levels": [10, 10, 10, 10, 10],
|
||||
"marker-high-levels": [100, 100, 100, 100, 100]
|
||||
}
|
|
@ -1,6 +1,15 @@
|
|||
"""Tests for the IPP config flow."""
|
||||
import dataclasses
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from pyipp import (
|
||||
IPPConnectionError,
|
||||
IPPConnectionUpgradeRequired,
|
||||
IPPError,
|
||||
IPPParseError,
|
||||
IPPVersionNotSupportedError,
|
||||
)
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.ipp.const import CONF_BASE_PATH, DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF
|
||||
|
@ -12,11 +21,11 @@ from . import (
|
|||
MOCK_USER_INPUT,
|
||||
MOCK_ZEROCONF_IPP_SERVICE_INFO,
|
||||
MOCK_ZEROCONF_IPPS_SERVICE_INFO,
|
||||
init_integration,
|
||||
mock_connection,
|
||||
)
|
||||
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
pytestmark = pytest.mark.usefixtures("mock_setup_entry")
|
||||
|
||||
|
||||
async def test_show_user_form(hass: HomeAssistant) -> None:
|
||||
|
@ -31,11 +40,10 @@ async def test_show_user_form(hass: HomeAssistant) -> None:
|
|||
|
||||
|
||||
async def test_show_zeroconf_form(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test that the zeroconf confirmation form is served."""
|
||||
mock_connection(aioclient_mock)
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
|
@ -49,10 +57,11 @@ async def test_show_zeroconf_form(
|
|||
|
||||
|
||||
async def test_connection_error(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we show user form on IPP connection error."""
|
||||
mock_connection(aioclient_mock, conn_error=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPConnectionError
|
||||
|
||||
user_input = MOCK_USER_INPUT.copy()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -67,10 +76,11 @@ async def test_connection_error(
|
|||
|
||||
|
||||
async def test_zeroconf_connection_error(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort zeroconf flow on IPP connection error."""
|
||||
mock_connection(aioclient_mock, conn_error=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPConnectionError
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -84,10 +94,11 @@ async def test_zeroconf_connection_error(
|
|||
|
||||
|
||||
async def test_zeroconf_confirm_connection_error(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort zeroconf flow on IPP connection error."""
|
||||
mock_connection(aioclient_mock, conn_error=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPConnectionError
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -99,10 +110,11 @@ async def test_zeroconf_confirm_connection_error(
|
|||
|
||||
|
||||
async def test_user_connection_upgrade_required(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we show the user form if connection upgrade required by server."""
|
||||
mock_connection(aioclient_mock, conn_upgrade_error=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPConnectionUpgradeRequired
|
||||
|
||||
user_input = MOCK_USER_INPUT.copy()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -117,10 +129,11 @@ async def test_user_connection_upgrade_required(
|
|||
|
||||
|
||||
async def test_zeroconf_connection_upgrade_required(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort zeroconf flow on IPP connection error."""
|
||||
mock_connection(aioclient_mock, conn_upgrade_error=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPConnectionUpgradeRequired
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -134,10 +147,11 @@ async def test_zeroconf_connection_upgrade_required(
|
|||
|
||||
|
||||
async def test_user_parse_error(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort user flow on IPP parse error."""
|
||||
mock_connection(aioclient_mock, parse_error=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPParseError
|
||||
|
||||
user_input = MOCK_USER_INPUT.copy()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -151,10 +165,11 @@ async def test_user_parse_error(
|
|||
|
||||
|
||||
async def test_zeroconf_parse_error(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort zeroconf flow on IPP parse error."""
|
||||
mock_connection(aioclient_mock, parse_error=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPParseError
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -168,10 +183,11 @@ async def test_zeroconf_parse_error(
|
|||
|
||||
|
||||
async def test_user_ipp_error(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort the user flow on IPP error."""
|
||||
mock_connection(aioclient_mock, ipp_error=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPError
|
||||
|
||||
user_input = MOCK_USER_INPUT.copy()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -185,10 +201,11 @@ async def test_user_ipp_error(
|
|||
|
||||
|
||||
async def test_zeroconf_ipp_error(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort zeroconf flow on IPP error."""
|
||||
mock_connection(aioclient_mock, ipp_error=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPError
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -202,10 +219,11 @@ async def test_zeroconf_ipp_error(
|
|||
|
||||
|
||||
async def test_user_ipp_version_error(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort user flow on IPP version not supported error."""
|
||||
mock_connection(aioclient_mock, version_not_supported=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPVersionNotSupportedError
|
||||
|
||||
user_input = {**MOCK_USER_INPUT}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -219,10 +237,11 @@ async def test_user_ipp_version_error(
|
|||
|
||||
|
||||
async def test_zeroconf_ipp_version_error(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort zeroconf flow on IPP version not supported error."""
|
||||
mock_connection(aioclient_mock, version_not_supported=True)
|
||||
mock_ipp_config_flow.printer.side_effect = IPPVersionNotSupportedError
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -236,10 +255,12 @@ async def test_zeroconf_ipp_version_error(
|
|||
|
||||
|
||||
async def test_user_device_exists_abort(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort user flow if printer already configured."""
|
||||
await init_integration(hass, aioclient_mock, skip_setup=True)
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
user_input = MOCK_USER_INPUT.copy()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -253,10 +274,12 @@ async def test_user_device_exists_abort(
|
|||
|
||||
|
||||
async def test_zeroconf_device_exists_abort(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort zeroconf flow if printer already configured."""
|
||||
await init_integration(hass, aioclient_mock, skip_setup=True)
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -270,10 +293,12 @@ async def test_zeroconf_device_exists_abort(
|
|||
|
||||
|
||||
async def test_zeroconf_with_uuid_device_exists_abort(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test we abort zeroconf flow if printer already configured."""
|
||||
await init_integration(hass, aioclient_mock, skip_setup=True)
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
discovery_info.properties = {
|
||||
|
@ -292,10 +317,12 @@ async def test_zeroconf_with_uuid_device_exists_abort(
|
|||
|
||||
|
||||
async def test_zeroconf_empty_unique_id(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test zeroconf flow if printer lacks (empty) unique identification."""
|
||||
mock_connection(aioclient_mock, no_unique_id=True)
|
||||
printer = mock_ipp_config_flow.printer.return_value
|
||||
printer.unique_id = None
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
discovery_info.properties = {
|
||||
|
@ -312,10 +339,12 @@ async def test_zeroconf_empty_unique_id(
|
|||
|
||||
|
||||
async def test_zeroconf_no_unique_id(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test zeroconf flow if printer lacks unique identification."""
|
||||
mock_connection(aioclient_mock, no_unique_id=True)
|
||||
printer = mock_ipp_config_flow.printer.return_value
|
||||
printer.unique_id = None
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
|
@ -328,11 +357,10 @@ async def test_zeroconf_no_unique_id(
|
|||
|
||||
|
||||
async def test_full_user_flow_implementation(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test the full manual user flow from start to finish."""
|
||||
mock_connection(aioclient_mock)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_USER},
|
||||
|
@ -341,11 +369,10 @@ async def test_full_user_flow_implementation(
|
|||
assert result["step_id"] == "user"
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
|
||||
with patch("homeassistant.components.ipp.async_setup_entry", return_value=True):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_HOST: "192.168.1.31", CONF_BASE_PATH: "/ipp/print"},
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_HOST: "192.168.1.31", CONF_BASE_PATH: "/ipp/print"},
|
||||
)
|
||||
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "192.168.1.31"
|
||||
|
@ -359,11 +386,10 @@ async def test_full_user_flow_implementation(
|
|||
|
||||
|
||||
async def test_full_zeroconf_flow_implementation(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test the full manual user flow from start to finish."""
|
||||
mock_connection(aioclient_mock)
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPP_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
|
@ -374,10 +400,9 @@ async def test_full_zeroconf_flow_implementation(
|
|||
assert result["step_id"] == "zeroconf_confirm"
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
|
||||
with patch("homeassistant.components.ipp.async_setup_entry", return_value=True):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "EPSON XP-6000 Series"
|
||||
|
@ -393,11 +418,10 @@ async def test_full_zeroconf_flow_implementation(
|
|||
|
||||
|
||||
async def test_full_zeroconf_tls_flow_implementation(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_ipp_config_flow: MagicMock,
|
||||
) -> None:
|
||||
"""Test the full manual user flow from start to finish."""
|
||||
mock_connection(aioclient_mock, ssl=True)
|
||||
|
||||
discovery_info = dataclasses.replace(MOCK_ZEROCONF_IPPS_SERVICE_INFO)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
|
@ -409,10 +433,9 @@ async def test_full_zeroconf_tls_flow_implementation(
|
|||
assert result["type"] == FlowResultType.FORM
|
||||
assert result["description_placeholders"] == {CONF_NAME: "EPSON XP-6000 Series"}
|
||||
|
||||
with patch("homeassistant.components.ipp.async_setup_entry", return_value=True):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "EPSON XP-6000 Series"
|
||||
|
|
|
@ -1,33 +1,45 @@
|
|||
"""Tests for the IPP integration."""
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from pyipp import IPPConnectionError
|
||||
|
||||
from homeassistant.components.ipp.const import DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import init_integration
|
||||
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@patch(
|
||||
"homeassistant.components.ipp.coordinator.IPP._request",
|
||||
side_effect=IPPConnectionError,
|
||||
)
|
||||
async def test_config_entry_not_ready(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
mock_request: MagicMock, hass: HomeAssistant, mock_config_entry: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test the IPP configuration entry not ready."""
|
||||
entry = await init_integration(hass, aioclient_mock, conn_error=True)
|
||||
assert entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_unload_config_entry(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test the IPP configuration entry unloading."""
|
||||
entry = await init_integration(hass, aioclient_mock)
|
||||
|
||||
assert hass.data[DOMAIN]
|
||||
assert entry.entry_id in hass.data[DOMAIN]
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
|
||||
await hass.config_entries.async_unload(entry.entry_id)
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert entry.entry_id not in hass.data[DOMAIN]
|
||||
assert entry.state is ConfigEntryState.NOT_LOADED
|
||||
assert mock_request.call_count == 1
|
||||
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_load_unload_config_entry(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_ipp: AsyncMock,
|
||||
) -> None:
|
||||
"""Test the IPP configuration entry loading/unloading."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.entry_id in hass.data[DOMAIN]
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
await hass.config_entries.async_unload(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_config_entry.entry_id not in hass.data[DOMAIN]
|
||||
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
|
|
|
@ -1,119 +1,105 @@
|
|||
"""Tests for the IPP sensor platform."""
|
||||
from datetime import datetime
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from homeassistant.components.ipp.const import DOMAIN
|
||||
from homeassistant.components.sensor import (
|
||||
ATTR_OPTIONS as SENSOR_ATTR_OPTIONS,
|
||||
DOMAIN as SENSOR_DOMAIN,
|
||||
)
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.sensor import ATTR_OPTIONS
|
||||
from homeassistant.const import ATTR_ICON, ATTR_UNIT_OF_MEASUREMENT, PERCENTAGE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import init_integration, mock_connection
|
||||
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.mark.freeze_time("2019-11-11 09:10:32+00:00")
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_sensors(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
init_integration: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test the creation and values of the IPP sensors."""
|
||||
mock_connection(aioclient_mock)
|
||||
|
||||
entry = await init_integration(hass, aioclient_mock, skip_setup=True)
|
||||
registry = er.async_get(hass)
|
||||
|
||||
# Pre-create registry entries for disabled by default sensors
|
||||
registry.async_get_or_create(
|
||||
SENSOR_DOMAIN,
|
||||
DOMAIN,
|
||||
"cfe92100-67c4-11d4-a45f-f8d027761251_uptime",
|
||||
suggested_object_id="epson_xp_6000_series_uptime",
|
||||
disabled_by=None,
|
||||
)
|
||||
|
||||
test_time = datetime(2019, 11, 11, 9, 10, 32, tzinfo=dt_util.UTC)
|
||||
with patch("homeassistant.components.ipp.sensor.utcnow", return_value=test_time):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("sensor.epson_xp_6000_series")
|
||||
state = hass.states.get("sensor.test_ha_1000_series")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_ICON) == "mdi:printer"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None
|
||||
assert state.attributes.get(SENSOR_ATTR_OPTIONS) == ["idle", "printing", "stopped"]
|
||||
assert state.attributes.get(ATTR_OPTIONS) == ["idle", "printing", "stopped"]
|
||||
|
||||
entry = registry.async_get("sensor.epson_xp_6000_series")
|
||||
entry = entity_registry.async_get("sensor.test_ha_1000_series")
|
||||
assert entry
|
||||
assert entry.translation_key == "printer"
|
||||
|
||||
state = hass.states.get("sensor.epson_xp_6000_series_black_ink")
|
||||
state = hass.states.get("sensor.test_ha_1000_series_black_ink")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_ICON) == "mdi:water"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is PERCENTAGE
|
||||
assert state.state == "58"
|
||||
|
||||
state = hass.states.get("sensor.epson_xp_6000_series_photo_black_ink")
|
||||
state = hass.states.get("sensor.test_ha_1000_series_photo_black_ink")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_ICON) == "mdi:water"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is PERCENTAGE
|
||||
assert state.state == "98"
|
||||
|
||||
state = hass.states.get("sensor.epson_xp_6000_series_cyan_ink")
|
||||
state = hass.states.get("sensor.test_ha_1000_series_cyan_ink")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_ICON) == "mdi:water"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is PERCENTAGE
|
||||
assert state.state == "91"
|
||||
|
||||
state = hass.states.get("sensor.epson_xp_6000_series_yellow_ink")
|
||||
state = hass.states.get("sensor.test_ha_1000_series_yellow_ink")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_ICON) == "mdi:water"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is PERCENTAGE
|
||||
assert state.state == "95"
|
||||
|
||||
state = hass.states.get("sensor.epson_xp_6000_series_magenta_ink")
|
||||
state = hass.states.get("sensor.test_ha_1000_series_magenta_ink")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_ICON) == "mdi:water"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is PERCENTAGE
|
||||
assert state.state == "73"
|
||||
|
||||
state = hass.states.get("sensor.epson_xp_6000_series_uptime")
|
||||
state = hass.states.get("sensor.test_ha_1000_series_uptime")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_ICON) == "mdi:clock-outline"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) is None
|
||||
assert state.state == "2019-10-26T15:37:00+00:00"
|
||||
assert state.state == "2019-11-11T09:10:02+00:00"
|
||||
|
||||
entry = registry.async_get("sensor.epson_xp_6000_series_uptime")
|
||||
entry = entity_registry.async_get("sensor.test_ha_1000_series_uptime")
|
||||
assert entry
|
||||
assert entry.unique_id == "cfe92100-67c4-11d4-a45f-f8d027761251_uptime"
|
||||
|
||||
|
||||
async def test_disabled_by_default_sensors(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
init_integration: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test the disabled by default IPP sensors."""
|
||||
await init_integration(hass, aioclient_mock)
|
||||
registry = er.async_get(hass)
|
||||
|
||||
state = hass.states.get("sensor.epson_xp_6000_series_uptime")
|
||||
state = hass.states.get("sensor.test_ha_1000_series_uptime")
|
||||
assert state is None
|
||||
|
||||
entry = registry.async_get("sensor.epson_xp_6000_series_uptime")
|
||||
entry = registry.async_get("sensor.test_ha_1000_series_uptime")
|
||||
assert entry
|
||||
assert entry.disabled
|
||||
assert entry.disabled_by is er.RegistryEntryDisabler.INTEGRATION
|
||||
|
||||
|
||||
async def test_missing_entry_unique_id(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_ipp: AsyncMock,
|
||||
) -> None:
|
||||
"""Test the unique_id of IPP sensor when printer is missing identifiers."""
|
||||
entry = await init_integration(hass, aioclient_mock, uuid=None, unique_id=None)
|
||||
mock_config_entry.unique_id = None
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
registry = er.async_get(hass)
|
||||
|
||||
entity = registry.async_get("sensor.epson_xp_6000_series")
|
||||
entity = registry.async_get("sensor.test_ha_1000_series")
|
||||
assert entity
|
||||
assert entity.unique_id == f"{entry.entry_id}_printer"
|
||||
assert entity.unique_id == f"{mock_config_entry.entry_id}_printer"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue