diff --git a/tests/components/brother/__init__.py b/tests/components/brother/__init__.py index b5a3f8ed5ef..7b4e937a9f8 100644 --- a/tests/components/brother/__init__.py +++ b/tests/components/brother/__init__.py @@ -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() diff --git a/tests/components/brother/conftest.py b/tests/components/brother/conftest.py index 1834cb2c36b..d546df731a9 100644 --- a/tests/components/brother/conftest.py +++ b/tests/components/brother/conftest.py @@ -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"}, + ) diff --git a/tests/components/brother/fixtures/printer_data.json b/tests/components/brother/fixtures/printer_data.json deleted file mode 100644 index aa9ce8cac62..00000000000 --- a/tests/components/brother/fixtures/printer_data.json +++ /dev/null @@ -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" -} diff --git a/tests/components/brother/snapshots/test_diagnostics.ambr b/tests/components/brother/snapshots/test_diagnostics.ambr index 262f9c75fd6..614588bf829 100644 --- a/tests/components/brother/snapshots/test_diagnostics.ambr +++ b/tests/components/brother/snapshots/test_diagnostics.ambr @@ -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', diff --git a/tests/components/brother/test_config_flow.py b/tests/components/brother/test_config_flow.py index a476ec8f579..3a9aff48e90 100644 --- a/tests/components/brother/test_config_flow.py +++ b/tests/components/brother/test_config_flow.py @@ -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" diff --git a/tests/components/brother/test_diagnostics.py b/tests/components/brother/test_diagnostics.py index 2ea9faa151e..117990b6470 100644 --- a/tests/components/brother/test_diagnostics.py +++ b/tests/components/brother/test_diagnostics.py @@ -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 diff --git a/tests/components/brother/test_init.py b/tests/components/brother/test_init.py index ef076aacab2..2b366348b03 100644 --- a/tests/components/brother/test_init.py +++ b/tests/components/brother/test_init.py @@ -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 diff --git a/tests/components/brother/test_sensor.py b/tests/components/brother/test_sensor.py index 069a5ddc152..7736b9257ee 100644 --- a/tests/components/brother/test_sensor.py +++ b/tests/components/brother/test_sensor.py @@ -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