Refactor tests for Brother integration (#117377)

* Refactor tests - step 1

* Remove fixture

* Refactor test_init

* Refactor test_diagnostics

* Refactor test_config_flow

* Increase test coverage

* Cleaning

* Cleaning

* Check config entry state in test_async_setup_entry

* Simplify patching

* Use AsyncMock when patching

---------

Co-authored-by: Maciej Bieniek <478555+bieniu@users.noreply.github.com>
This commit is contained in:
Maciej Bieniek 2024-05-19 20:41:47 +02:00 committed by GitHub
parent d2008ffdd7
commit 826f6c6f7e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 332 additions and 418 deletions

View file

@ -1,37 +1,15 @@
"""Tests for Brother Printer integration."""
import json
from unittest.mock import patch
from homeassistant.components.brother.const import DOMAIN
from homeassistant.const import CONF_HOST, CONF_TYPE
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry, load_fixture
from tests.common import MockConfigEntry
async def init_integration(
hass: HomeAssistant, skip_setup: bool = False
hass: HomeAssistant, entry: MockConfigEntry
) -> MockConfigEntry:
"""Set up the Brother integration in Home Assistant."""
entry = MockConfigEntry(
domain=DOMAIN,
title="HL-L2340DW 0123456789",
unique_id="0123456789",
data={CONF_HOST: "localhost", CONF_TYPE: "laser"},
)
entry.add_to_hass(hass)
if not skip_setup:
with (
patch("brother.Brother.initialize"),
patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("printer_data.json", "brother")),
),
):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
return entry
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()

View file

@ -1,10 +1,81 @@
"""Test fixtures for brother."""
from collections.abc import Generator
from datetime import UTC, datetime
from unittest.mock import AsyncMock, patch
from brother import BrotherSensors
import pytest
from homeassistant.components.brother.const import DOMAIN
from homeassistant.const import CONF_HOST, CONF_TYPE
from tests.common import MockConfigEntry
BROTHER_DATA = BrotherSensors(
belt_unit_remaining_life=97,
belt_unit_remaining_pages=48436,
black_counter=None,
black_drum_counter=1611,
black_drum_remaining_life=92,
black_drum_remaining_pages=16389,
black_ink_remaining=None,
black_ink_status=None,
black_ink=None,
black_toner_remaining=75,
black_toner_status=1,
black_toner=80,
bw_counter=709,
color_counter=902,
cyan_counter=None,
cyan_drum_counter=1611,
cyan_drum_remaining_life=92,
cyan_drum_remaining_pages=16389,
cyan_ink_remaining=None,
cyan_ink_status=None,
cyan_ink=None,
cyan_toner_remaining=10,
cyan_toner_status=1,
cyan_toner=10,
drum_counter=986,
drum_remaining_life=92,
drum_remaining_pages=11014,
drum_status=1,
duplex_unit_pages_counter=538,
fuser_remaining_life=97,
fuser_unit_remaining_pages=None,
image_counter=None,
laser_remaining_life=None,
laser_unit_remaining_pages=48389,
magenta_counter=None,
magenta_drum_counter=1611,
magenta_drum_remaining_life=92,
magenta_drum_remaining_pages=16389,
magenta_ink_remaining=None,
magenta_ink_status=None,
magenta_ink=None,
magenta_toner_remaining=8,
magenta_toner_status=2,
magenta_toner=10,
page_counter=986,
pf_kit_1_remaining_life=98,
pf_kit_1_remaining_pages=48741,
pf_kit_mp_remaining_life=None,
pf_kit_mp_remaining_pages=None,
status="waiting",
uptime=datetime(2024, 3, 3, 15, 4, 24, tzinfo=UTC),
yellow_counter=None,
yellow_drum_counter=1611,
yellow_drum_remaining_life=92,
yellow_drum_remaining_pages=16389,
yellow_ink_remaining=None,
yellow_ink_status=None,
yellow_ink=None,
yellow_toner_remaining=2,
yellow_toner_status=2,
yellow_toner=10,
)
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock, None, None]:
@ -13,3 +84,34 @@ def mock_setup_entry() -> Generator[AsyncMock, None, None]:
"homeassistant.components.brother.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry
@pytest.fixture
def mock_brother_client() -> Generator[AsyncMock, None, None]:
"""Mock Brother client."""
with (
patch("homeassistant.components.brother.Brother", autospec=True) as mock_client,
patch(
"homeassistant.components.brother.config_flow.Brother",
new=mock_client,
),
):
client = mock_client.create.return_value
client.async_update.return_value = BROTHER_DATA
client.serial = "0123456789"
client.mac = "AA:BB:CC:DD:EE:FF"
client.model = "HL-L2340DW"
client.firmware = "1.2.3"
yield client
@pytest.fixture
def mock_config_entry() -> MockConfigEntry:
"""Mock a config entry."""
return MockConfigEntry(
domain=DOMAIN,
title="HL-L2340DW 0123456789",
unique_id="0123456789",
data={CONF_HOST: "localhost", CONF_TYPE: "laser"},
)

View file

@ -1,77 +0,0 @@
{
"1.3.6.1.2.1.1.3.0": "413613515",
"1.3.6.1.2.1.43.10.2.1.4.1.1": "986",
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.10.0": [
"000104000003da",
"010104000002c5",
"02010400000386",
"0601040000021a",
"0701040000012d",
"080104000000ed"
],
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.17.0": "1.17",
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.8.0": [
"110104000003da",
"31010400000001",
"32010400000001",
"33010400000002",
"34010400000002",
"35010400000001",
"410104000023f0",
"54010400000001",
"55010400000001",
"63010400000001",
"68010400000001",
"690104000025e4",
"6a0104000025e4",
"6d010400002648",
"6f010400001d4c",
"700104000003e8",
"71010400000320",
"720104000000c8",
"7301040000064b",
"7401040000064b",
"7501040000064b",
"76010400000001",
"77010400000001",
"78010400000001",
"790104000023f0",
"7a0104000023f0",
"7b0104000023f0",
"7e01040000064b",
"800104000023f0",
"81010400000050",
"8201040000000a",
"8301040000000a",
"8401040000000a",
"8601040000000a"
],
"1.3.6.1.4.1.2435.2.3.9.1.1.7.0": "MFG:Brother;CMD:PJL,HBP,URF;MDL:HL-L2340DW series;CLS:PRINTER;CID:Brother Laser Type1;URF:W8,CP1,IS4-1,MT1-3-4-5-8,OB10,PQ4,RS300-600,V1.3,DM1;",
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.11.0": [
"7301040000bd05",
"7701040000be65",
"82010400002b06",
"8801040000bd34",
"a4010400004005",
"a5010400004005",
"a6010400004005",
"a7010400004005"
],
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.21.0": [
"00002302000025",
"00020016010200",
"00210200022202",
"020000a1040000"
],
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.20.0": [
"00a40100a50100",
"0100a301008801",
"01017301007701",
"870100a10100a2",
"a60100a70100a0"
],
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.1.0": "0123456789",
"1.3.6.1.4.1.2435.2.3.9.4.2.1.5.4.5.2.0": "WAITING ",
"1.3.6.1.2.1.43.7.1.1.4.1.1": "2004",
"1.3.6.1.2.1.2.2.1.6.1": "aa:bb:cc:dd:ee:ff"
}

View file

@ -52,7 +52,7 @@
'pf_kit_mp_remaining_life': None,
'pf_kit_mp_remaining_pages': None,
'status': 'waiting',
'uptime': '2019-09-24T12:14:56+00:00',
'uptime': '2024-03-03T15:04:24+00:00',
'yellow_counter': None,
'yellow_drum_counter': 1611,
'yellow_drum_remaining_life': 92,
@ -64,7 +64,7 @@
'yellow_toner_remaining': 2,
'yellow_toner_status': 2,
}),
'firmware': '1.17',
'firmware': '1.2.3',
'info': dict({
'host': 'localhost',
'type': 'laser',

View file

@ -1,8 +1,7 @@
"""Define tests for the Brother Printer config flow."""
from ipaddress import ip_address
import json
from unittest.mock import patch
from unittest.mock import AsyncMock, patch
from brother import SnmpError, UnsupportedModelError
import pytest
@ -14,7 +13,9 @@ from homeassistant.const import CONF_HOST, CONF_TYPE
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry, load_fixture
from . import init_integration
from tests.common import MockConfigEntry
CONFIG = {CONF_HOST: "127.0.0.1", CONF_TYPE: "laser"}
@ -31,65 +32,21 @@ async def test_show_form(hass: HomeAssistant) -> None:
assert result["step_id"] == "user"
async def test_create_entry_with_hostname(hass: HomeAssistant) -> None:
"""Test that the user step works with printer hostname."""
with (
patch("brother.Brother.initialize"),
patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("printer_data.json", "brother")),
),
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_USER},
data={CONF_HOST: "example.local", CONF_TYPE: "laser"},
)
@pytest.mark.parametrize("host", ["example.local", "127.0.0.1", "2001:db8::1428:57ab"])
async def test_create_entry(
hass: HomeAssistant, host: str, mock_brother_client: AsyncMock
) -> None:
"""Test that the user step works with printer hostname/IPv4/IPv6."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_USER},
data={CONF_HOST: host, CONF_TYPE: "laser"},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "HL-L2340DW 0123456789"
assert result["data"][CONF_HOST] == "example.local"
assert result["data"][CONF_TYPE] == "laser"
async def test_create_entry_with_ipv4_address(hass: HomeAssistant) -> None:
"""Test that the user step works with printer IPv4 address."""
with (
patch("brother.Brother.initialize"),
patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("printer_data.json", "brother")),
),
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}, data=CONFIG
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "HL-L2340DW 0123456789"
assert result["data"][CONF_HOST] == "127.0.0.1"
assert result["data"][CONF_TYPE] == "laser"
async def test_create_entry_with_ipv6_address(hass: HomeAssistant) -> None:
"""Test that the user step works with printer IPv6 address."""
with (
patch("brother.Brother.initialize"),
patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("printer_data.json", "brother")),
),
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_USER},
data={CONF_HOST: "2001:db8::1428:57ab", CONF_TYPE: "laser"},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "HL-L2340DW 0123456789"
assert result["data"][CONF_HOST] == "2001:db8::1428:57ab"
assert result["data"][CONF_TYPE] == "laser"
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "HL-L2340DW 0123456789"
assert result["data"][CONF_HOST] == host
assert result["data"][CONF_TYPE] == "laser"
async def test_invalid_hostname(hass: HomeAssistant) -> None:
@ -103,97 +60,87 @@ async def test_invalid_hostname(hass: HomeAssistant) -> None:
assert result["errors"] == {CONF_HOST: "wrong_host"}
@pytest.mark.parametrize("exc", [ConnectionError, TimeoutError])
async def test_connection_error(hass: HomeAssistant, exc: Exception) -> None:
@pytest.mark.parametrize(
("exc", "base_error"),
[
(ConnectionError, "cannot_connect"),
(TimeoutError, "cannot_connect"),
(SnmpError("SNMP error"), "snmp_error"),
],
)
async def test_errors(
hass: HomeAssistant, exc: Exception, base_error: str, mock_brother_client: AsyncMock
) -> None:
"""Test connection to host error."""
with (
patch("brother.Brother.initialize"),
patch("brother.Brother._get_data", side_effect=exc),
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}, data=CONFIG
)
mock_brother_client.async_update.side_effect = exc
assert result["errors"] == {"base": "cannot_connect"}
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}, data=CONFIG
)
async def test_snmp_error(hass: HomeAssistant) -> None:
"""Test SNMP error."""
with (
patch("brother.Brother.initialize"),
patch("brother.Brother._get_data", side_effect=SnmpError("error")),
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}, data=CONFIG
)
assert result["errors"] == {"base": "snmp_error"}
assert result["errors"] == {"base": base_error}
async def test_unsupported_model_error(hass: HomeAssistant) -> None:
"""Test unsupported printer model error."""
with (
patch("brother.Brother.initialize"),
patch("brother.Brother._get_data", side_effect=UnsupportedModelError("error")),
with patch(
"homeassistant.components.brother.Brother.create",
new=AsyncMock(side_effect=UnsupportedModelError("error")),
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}, data=CONFIG
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "unsupported_model"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "unsupported_model"
async def test_device_exists_abort(hass: HomeAssistant) -> None:
async def test_device_exists_abort(
hass: HomeAssistant,
mock_brother_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test we abort config flow if Brother printer already configured."""
with (
patch("brother.Brother.initialize"),
patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("printer_data.json", "brother")),
),
):
MockConfigEntry(domain=DOMAIN, unique_id="0123456789", data=CONFIG).add_to_hass(
hass
)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}, data=CONFIG
)
await init_integration(hass, mock_config_entry)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}, data=CONFIG
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
@pytest.mark.parametrize("exc", [ConnectionError, TimeoutError, SnmpError("error")])
async def test_zeroconf_exception(hass: HomeAssistant, exc: Exception) -> None:
async def test_zeroconf_exception(
hass: HomeAssistant, exc: Exception, mock_brother_client: AsyncMock
) -> None:
"""Test we abort zeroconf flow on exception."""
with (
patch("brother.Brother.initialize"),
patch("brother.Brother._get_data", side_effect=exc),
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=zeroconf.ZeroconfServiceInfo(
ip_address=ip_address("127.0.0.1"),
ip_addresses=[ip_address("127.0.0.1")],
hostname="example.local.",
name="Brother Printer",
port=None,
properties={},
type="mock_type",
),
)
mock_brother_client.async_update.side_effect = exc
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "cannot_connect"
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=zeroconf.ZeroconfServiceInfo(
ip_address=ip_address("127.0.0.1"),
ip_addresses=[ip_address("127.0.0.1")],
hostname="example.local.",
name="Brother Printer",
port=None,
properties={},
type="mock_type",
),
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "cannot_connect"
async def test_zeroconf_unsupported_model(hass: HomeAssistant) -> None:
"""Test unsupported printer model error."""
with (
patch("brother.Brother.initialize"),
patch("brother.Brother._get_data") as mock_get_data,
with patch(
"homeassistant.components.brother.Brother.create",
new=AsyncMock(side_effect=UnsupportedModelError("error")),
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -209,46 +156,37 @@ async def test_zeroconf_unsupported_model(hass: HomeAssistant) -> None:
),
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "unsupported_model"
assert len(mock_get_data.mock_calls) == 0
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "unsupported_model"
async def test_zeroconf_device_exists_abort(hass: HomeAssistant) -> None:
async def test_zeroconf_device_exists_abort(
hass: HomeAssistant,
mock_brother_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test we abort zeroconf flow if Brother printer already configured."""
with (
patch("brother.Brother.initialize"),
patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("printer_data.json", "brother")),
await init_integration(hass, mock_config_entry)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=zeroconf.ZeroconfServiceInfo(
ip_address=ip_address("127.0.0.1"),
ip_addresses=[ip_address("127.0.0.1")],
hostname="example.local.",
name="Brother Printer",
port=None,
properties={},
type="mock_type",
),
):
entry = MockConfigEntry(
domain=DOMAIN,
unique_id="0123456789",
data={CONF_HOST: "example.local", CONF_TYPE: "laser"},
)
entry.add_to_hass(hass)
)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=zeroconf.ZeroconfServiceInfo(
ip_address=ip_address("127.0.0.1"),
ip_addresses=[ip_address("127.0.0.1")],
hostname="example.local.",
name="Brother Printer",
port=None,
properties={},
type="mock_type",
),
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
# Test config entry got updated with latest IP
assert entry.data["host"] == "127.0.0.1"
assert mock_config_entry.data[CONF_HOST] == "127.0.0.1"
async def test_zeroconf_no_probe_existing_device(hass: HomeAssistant) -> None:
@ -256,8 +194,8 @@ async def test_zeroconf_no_probe_existing_device(hass: HomeAssistant) -> None:
entry = MockConfigEntry(domain=DOMAIN, unique_id="0123456789", data=CONFIG)
entry.add_to_hass(hass)
with (
patch("brother.Brother.initialize"),
patch("brother.Brother._get_data") as mock_get_data,
patch("homeassistant.components.brother.Brother.initialize"),
patch("homeassistant.components.brother.Brother._get_data") as mock_get_data,
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
@ -279,39 +217,34 @@ async def test_zeroconf_no_probe_existing_device(hass: HomeAssistant) -> None:
assert len(mock_get_data.mock_calls) == 0
async def test_zeroconf_confirm_create_entry(hass: HomeAssistant) -> None:
async def test_zeroconf_confirm_create_entry(
hass: HomeAssistant, mock_brother_client: AsyncMock
) -> None:
"""Test zeroconf confirmation and create config entry."""
with (
patch("brother.Brother.initialize"),
patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("printer_data.json", "brother")),
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=zeroconf.ZeroconfServiceInfo(
ip_address=ip_address("127.0.0.1"),
ip_addresses=[ip_address("127.0.0.1")],
hostname="example.local.",
name="Brother Printer",
port=None,
properties={},
type="mock_type",
),
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=zeroconf.ZeroconfServiceInfo(
ip_address=ip_address("127.0.0.1"),
ip_addresses=[ip_address("127.0.0.1")],
hostname="example.local.",
name="Brother Printer",
port=None,
properties={},
type="mock_type",
),
)
)
assert result["step_id"] == "zeroconf_confirm"
assert result["description_placeholders"]["model"] == "HL-L2340DW"
assert result["description_placeholders"]["serial_number"] == "0123456789"
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "zeroconf_confirm"
assert result["description_placeholders"]["model"] == "HL-L2340DW"
assert result["description_placeholders"]["serial_number"] == "0123456789"
assert result["type"] is FlowResultType.FORM
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_TYPE: "laser"}
)
result = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={CONF_TYPE: "laser"}
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "HL-L2340DW 0123456789"
assert result["data"][CONF_HOST] == "127.0.0.1"
assert result["data"][CONF_TYPE] == "laser"
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "HL-L2340DW 0123456789"
assert result["data"][CONF_HOST] == "127.0.0.1"
assert result["data"][CONF_TYPE] == "laser"

View file

@ -1,17 +1,14 @@
"""Test Brother diagnostics."""
from datetime import datetime
import json
from unittest.mock import Mock, patch
from unittest.mock import AsyncMock
from syrupy import SnapshotAssertion
from homeassistant.core import HomeAssistant
from homeassistant.util.dt import UTC
from . import init_integration
from tests.common import load_fixture
from tests.common import MockConfigEntry
from tests.components.diagnostics import get_diagnostics_for_config_entry
from tests.typing import ClientSessionGenerator
@ -19,23 +16,15 @@ from tests.typing import ClientSessionGenerator
async def test_entry_diagnostics(
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
mock_brother_client: AsyncMock,
mock_config_entry: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test config entry diagnostics."""
entry = await init_integration(hass, skip_setup=True)
await init_integration(hass, mock_config_entry)
test_time = datetime(2019, 11, 11, 9, 10, 32, tzinfo=UTC)
with (
patch("brother.Brother.initialize"),
patch("brother.datetime", now=Mock(return_value=test_time)),
patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("printer_data.json", "brother")),
),
):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
result = await get_diagnostics_for_config_entry(hass, hass_client, entry)
result = await get_diagnostics_for_config_entry(
hass, hass_client, mock_config_entry
)
assert result == snapshot

View file

@ -1,13 +1,13 @@
"""Test init of Brother integration."""
from unittest.mock import patch
from unittest.mock import AsyncMock, patch
from brother import SnmpError
import pytest
from homeassistant.components.brother.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_HOST, CONF_TYPE, STATE_UNAVAILABLE
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.core import HomeAssistant
from . import init_integration
@ -15,61 +15,76 @@ from . import init_integration
from tests.common import MockConfigEntry
async def test_async_setup_entry(hass: HomeAssistant) -> None:
async def test_async_setup_entry(
hass: HomeAssistant,
mock_brother_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test a successful setup entry."""
await init_integration(hass)
await init_integration(hass, mock_config_entry)
state = hass.states.get("sensor.hl_l2340dw_status")
assert state is not None
assert state.state != STATE_UNAVAILABLE
assert state.state == "waiting"
assert mock_config_entry.state is ConfigEntryState.LOADED
async def test_config_not_ready(hass: HomeAssistant) -> None:
async def test_config_not_ready(
hass: HomeAssistant,
mock_brother_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test for setup failure if connection to broker is missing."""
entry = MockConfigEntry(
domain=DOMAIN,
title="HL-L2340DW 0123456789",
unique_id="0123456789",
data={CONF_HOST: "localhost", CONF_TYPE: "laser"},
)
mock_brother_client.async_update.side_effect = ConnectionError
with (
patch("brother.Brother.initialize"),
patch("brother.Brother._get_data", side_effect=ConnectionError()),
):
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.SETUP_RETRY
await init_integration(hass, mock_config_entry)
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
@pytest.mark.parametrize("exc", [(SnmpError("SNMP Error")), (ConnectionError)])
async def test_error_on_init(hass: HomeAssistant, exc: Exception) -> None:
async def test_error_on_init(
hass: HomeAssistant, exc: Exception, mock_config_entry: MockConfigEntry
) -> None:
"""Test for error on init."""
entry = MockConfigEntry(
domain=DOMAIN,
title="HL-L2340DW 0123456789",
unique_id="0123456789",
data={CONF_HOST: "localhost", CONF_TYPE: "laser"},
)
with patch(
"homeassistant.components.brother.Brother.create",
new=AsyncMock(side_effect=exc),
):
await init_integration(hass, mock_config_entry)
with patch("brother.Brother.initialize", side_effect=exc):
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.SETUP_RETRY
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_unload_entry(hass: HomeAssistant) -> None:
async def test_unload_entry(
hass: HomeAssistant,
mock_brother_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test successful unload of entry."""
entry = await init_integration(hass)
await init_integration(hass, mock_config_entry)
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
assert entry.state is ConfigEntryState.LOADED
assert mock_config_entry.state is ConfigEntryState.LOADED
with patch("homeassistant.components.brother.lcd.unconfigure") as mock_unconfigure:
assert await hass.config_entries.async_unload(entry.entry_id)
assert await hass.config_entries.async_unload(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_unconfigure.called
assert entry.state is ConfigEntryState.NOT_LOADED
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
assert not hass.data.get(DOMAIN)
async def test_unconfigure_snmp_engine_on_ha_stop(
hass: HomeAssistant,
mock_brother_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test that the SNMP engine is unconfigured when HA stops."""
await init_integration(hass, mock_config_entry)
with patch(
"homeassistant.components.brother.utils.lcd.unconfigure"
) as mock_unconfigure:
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
await hass.async_block_till_done()
assert mock_unconfigure.called

View file

@ -1,23 +1,19 @@
"""Test sensor of Brother integration."""
from datetime import timedelta
import json
from unittest.mock import patch
from unittest.mock import AsyncMock, patch
from freezegun.api import FrozenDateTimeFactory
from syrupy import SnapshotAssertion
from homeassistant.components.brother.const import DOMAIN
from homeassistant.components.brother.const import DOMAIN, UPDATE_INTERVAL
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE, Platform
from homeassistant.const import STATE_UNAVAILABLE, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util.dt import utcnow
from . import init_integration
from tests.common import async_fire_time_changed, load_fixture, snapshot_platform
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
async def test_sensors(
@ -25,78 +21,56 @@ async def test_sensors(
entity_registry: er.EntityRegistry,
entity_registry_enabled_by_default: None,
snapshot: SnapshotAssertion,
freezer: FrozenDateTimeFactory,
mock_brother_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test states of the sensors."""
hass.config.set_time_zone("UTC")
freezer.move_to("2024-04-20 12:00:00+00:00")
with patch("homeassistant.components.brother.PLATFORMS", [Platform.SENSOR]):
entry = await init_integration(hass)
await init_integration(hass, mock_config_entry)
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
async def test_availability(hass: HomeAssistant) -> None:
async def test_availability(
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
mock_brother_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Ensure that we mark the entities unavailable correctly when device is offline."""
await init_integration(hass)
entity_id = "sensor.hl_l2340dw_status"
await init_integration(hass, mock_config_entry)
state = hass.states.get("sensor.hl_l2340dw_status")
state = hass.states.get(entity_id)
assert state
assert state.state != STATE_UNAVAILABLE
assert state.state == "waiting"
future = utcnow() + timedelta(minutes=5)
with (
patch("brother.Brother.initialize"),
patch("brother.Brother._get_data", side_effect=ConnectionError()),
):
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
mock_brother_client.async_update.side_effect = ConnectionError
freezer.tick(UPDATE_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get("sensor.hl_l2340dw_status")
assert state
assert state.state == STATE_UNAVAILABLE
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_UNAVAILABLE
future = utcnow() + timedelta(minutes=10)
with (
patch("brother.Brother.initialize"),
patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("printer_data.json", "brother")),
),
):
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
mock_brother_client.async_update.side_effect = None
freezer.tick(UPDATE_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get("sensor.hl_l2340dw_status")
assert state
assert state.state != STATE_UNAVAILABLE
assert state.state == "waiting"
async def test_manual_update_entity(hass: HomeAssistant) -> None:
"""Test manual update entity via service homeassistant/update_entity."""
await init_integration(hass)
data = json.loads(load_fixture("printer_data.json", "brother"))
await async_setup_component(hass, "homeassistant", {})
with patch(
"homeassistant.components.brother.Brother.async_update", return_value=data
) as mock_update:
await hass.services.async_call(
"homeassistant",
"update_entity",
{ATTR_ENTITY_ID: ["sensor.hl_l2340dw_status"]},
blocking=True,
)
assert len(mock_update.mock_calls) == 1
state = hass.states.get(entity_id)
assert state
assert state.state != STATE_UNAVAILABLE
assert state.state == "waiting"
async def test_unique_id_migration(
hass: HomeAssistant, entity_registry: er.EntityRegistry
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
mock_config_entry: MockConfigEntry,
mock_brother_client: AsyncMock,
) -> None:
"""Test states of the unique_id migration."""
@ -108,7 +82,7 @@ async def test_unique_id_migration(
disabled_by=None,
)
await init_integration(hass)
await init_integration(hass, mock_config_entry)
entry = entity_registry.async_get("sensor.hl_l2340dw_b_w_counter")
assert entry