From 21029b1d7b2dccac8f16607e77cd1297a277d502 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Mon, 6 Jan 2020 18:06:16 +0100 Subject: [PATCH] Add Brother Printer integration (#30359) * Init entities as unavailable when offline * Initial commit * Fix CODEOWNERS * CODEOWNERS * Run script.hassfest * Add initial test * Bump library * More tests * Tests * Add new sensors and fix KeyError * Fix unique_id and device_info * Fix check for configured device * More tests * Bump library version * Add uptime sensor * Use config entry unique ID * Run python3 -m script.gen_requirements_all * Fix pylint error * Remove pysnmp dependency * Raise ConfigEntryNotReady when device offline at HA start * Remove period from logging message * Generator simplification * Change raise_on_progress * Rename data to printer * Move update state to async_update * Remove unused _unit_of_measurement * Remove update of device_info * Suggested change for tests * Remove unnecessary argument * Suggested change --- .coveragerc | 3 + CODEOWNERS | 1 + homeassistant/components/brother/__init__.py | 102 ++++++++++++++ .../components/brother/config_flow.py | 69 +++++++++ homeassistant/components/brother/const.py | 132 ++++++++++++++++++ .../components/brother/manifest.json | 9 ++ homeassistant/components/brother/sensor.py | 104 ++++++++++++++ homeassistant/components/brother/strings.json | 23 +++ homeassistant/generated/config_flows.py | 1 + requirements_all.txt | 3 + requirements_test_all.txt | 3 + tests/components/brother/__init__.py | 1 + tests/components/brother/test_config_flow.py | 127 +++++++++++++++++ tests/fixtures/brother_printer_data.json | 17 +++ 14 files changed, 595 insertions(+) create mode 100644 homeassistant/components/brother/__init__.py create mode 100644 homeassistant/components/brother/config_flow.py create mode 100644 homeassistant/components/brother/const.py create mode 100644 homeassistant/components/brother/manifest.json create mode 100644 homeassistant/components/brother/sensor.py create mode 100644 homeassistant/components/brother/strings.json create mode 100644 tests/components/brother/__init__.py create mode 100644 tests/components/brother/test_config_flow.py create mode 100644 tests/fixtures/brother_printer_data.json diff --git a/.coveragerc b/.coveragerc index 4d4d962a9b3..dd486626c54 100644 --- a/.coveragerc +++ b/.coveragerc @@ -95,6 +95,9 @@ omit = homeassistant/components/broadlink/remote.py homeassistant/components/broadlink/sensor.py homeassistant/components/broadlink/switch.py + homeassistant/components/brother/__init__.py + homeassistant/components/brother/sensor.py + homeassistant/components/brother/const.py homeassistant/components/brottsplatskartan/sensor.py homeassistant/components/browser/* homeassistant/components/brunt/cover.py diff --git a/CODEOWNERS b/CODEOWNERS index 7940b5878ca..b9db06f8f56 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -51,6 +51,7 @@ homeassistant/components/blink/* @fronzbot homeassistant/components/bmw_connected_drive/* @gerard33 homeassistant/components/braviatv/* @robbiet480 homeassistant/components/broadlink/* @danielhiversen @felipediel +homeassistant/components/brother/* @bieniu homeassistant/components/brunt/* @eavanvalkenburg homeassistant/components/bt_smarthub/* @jxwolstenholme homeassistant/components/buienradar/* @mjj4791 @ties diff --git a/homeassistant/components/brother/__init__.py b/homeassistant/components/brother/__init__.py new file mode 100644 index 00000000000..ada740c5f10 --- /dev/null +++ b/homeassistant/components/brother/__init__.py @@ -0,0 +1,102 @@ +"""The Brother component.""" +import asyncio +from datetime import timedelta +import logging + +from brother import Brother, SnmpError, UnsupportedModel + +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_HOST, CONF_TYPE +from homeassistant.core import Config, HomeAssistant +from homeassistant.exceptions import ConfigEntryNotReady +from homeassistant.util import Throttle + +from .const import DOMAIN + +PLATFORMS = ["sensor"] + +DEFAULT_SCAN_INTERVAL = timedelta(seconds=30) + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup(hass: HomeAssistant, config: Config): + """Set up the Brother component.""" + hass.data[DOMAIN] = {} + return True + + +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): + """Set up Brother from a config entry.""" + host = entry.data[CONF_HOST] + kind = entry.data[CONF_TYPE] + + brother = BrotherPrinterData(host, kind) + + await brother.async_update() + + if not brother.available: + raise ConfigEntryNotReady() + + hass.data[DOMAIN][entry.entry_id] = brother + + for component in PLATFORMS: + hass.async_create_task( + hass.config_entries.async_forward_entry_setup(entry, component) + ) + + return True + + +async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry): + """Unload a config entry.""" + unload_ok = all( + await asyncio.gather( + *[ + hass.config_entries.async_forward_entry_unload(entry, component) + for component in PLATFORMS + ] + ) + ) + if unload_ok: + hass.data[DOMAIN].pop(entry.entry_id) + + return unload_ok + + +class BrotherPrinterData: + """Define an object to hold sensor data.""" + + def __init__(self, host, kind): + """Initialize.""" + self._brother = Brother(host, kind=kind) + self.host = host + self.model = None + self.serial = None + self.firmware = None + self.available = False + self.data = {} + self.unavailable_logged = False + + @Throttle(DEFAULT_SCAN_INTERVAL) + async def async_update(self): + """Update data via library.""" + try: + await self._brother.async_update() + except (ConnectionError, SnmpError, UnsupportedModel) as error: + if not self.unavailable_logged: + _LOGGER.error( + "Could not fetch data from %s, error: %s", self.host, error + ) + self.unavailable_logged = True + self.available = self._brother.available + return + + self.model = self._brother.model + self.serial = self._brother.serial + self.firmware = self._brother.firmware + self.available = self._brother.available + self.data = self._brother.data + if self.available and self.unavailable_logged: + _LOGGER.info("Printer %s is available again", self.host) + self.unavailable_logged = False diff --git a/homeassistant/components/brother/config_flow.py b/homeassistant/components/brother/config_flow.py new file mode 100644 index 00000000000..b95469977a7 --- /dev/null +++ b/homeassistant/components/brother/config_flow.py @@ -0,0 +1,69 @@ +"""Adds config flow for Brother Printer.""" +import ipaddress +import re + +from brother import Brother, SnmpError, UnsupportedModel +import voluptuous as vol + +from homeassistant import config_entries, exceptions +from homeassistant.const import CONF_HOST, CONF_TYPE + +from .const import DOMAIN, PRINTER_TYPES # pylint:disable=unused-import + +DATA_SCHEMA = vol.Schema( + { + vol.Required(CONF_HOST, default=""): str, + vol.Optional(CONF_TYPE, default="laser"): vol.In(PRINTER_TYPES), + } +) + + +def host_valid(host): + """Return True if hostname or IP address is valid.""" + try: + if ipaddress.ip_address(host).version == (4 or 6): + return True + except ValueError: + disallowed = re.compile(r"[^a-zA-Z\d\-]") + return all(x and not disallowed.search(x) for x in host.split(".")) + + +class BrotherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): + """Handle a config flow for Brother Printer.""" + + VERSION = 1 + CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL + + async def async_step_user(self, user_input=None): + """Handle the initial step.""" + errors = {} + + if user_input is not None: + try: + if not host_valid(user_input[CONF_HOST]): + raise InvalidHost() + + brother = Brother(user_input[CONF_HOST]) + await brother.async_update() + + await self.async_set_unique_id(brother.serial.lower()) + self._abort_if_unique_id_configured() + + title = f"{brother.model} {brother.serial}" + return self.async_create_entry(title=title, data=user_input) + except InvalidHost: + errors[CONF_HOST] = "wrong_host" + except ConnectionError: + errors["base"] = "connection_error" + except SnmpError: + errors["base"] = "snmp_error" + except UnsupportedModel: + return self.async_abort(reason="unsupported_model") + + return self.async_show_form( + step_id="user", data_schema=DATA_SCHEMA, errors=errors + ) + + +class InvalidHost(exceptions.HomeAssistantError): + """Error to indicate that hostname/IP address is invalid.""" diff --git a/homeassistant/components/brother/const.py b/homeassistant/components/brother/const.py new file mode 100644 index 00000000000..fdb7cd82b9c --- /dev/null +++ b/homeassistant/components/brother/const.py @@ -0,0 +1,132 @@ +"""Constants for Brother integration.""" +ATTR_BELT_UNIT_REMAINING_LIFE = "belt_unit_remaining_life" +ATTR_BLACK_INK_REMAINING = "black_ink_remaining" +ATTR_BLACK_TONER_REMAINING = "black_toner_remaining" +ATTR_BW_COUNTER = "b/w_counter" +ATTR_COLOR_COUNTER = "color_counter" +ATTR_CYAN_INK_REMAINING = "cyan_ink_remaining" +ATTR_CYAN_TONER_REMAINING = "cyan_toner_remaining" +ATTR_DRUM_COUNTER = "drum_counter" +ATTR_DRUM_REMAINING_LIFE = "drum_remaining_life" +ATTR_DRUM_REMAINING_PAGES = "drum_remaining_pages" +ATTR_FUSER_REMAINING_LIFE = "fuser_remaining_life" +ATTR_ICON = "icon" +ATTR_LABEL = "label" +ATTR_LASER_REMAINING_LIFE = "laser_remaining_life" +ATTR_MAGENTA_INK_REMAINING = "magenta_ink_remaining" +ATTR_MAGENTA_TONER_REMAINING = "magenta_toner_remaining" +ATTR_MANUFACTURER = "Brother" +ATTR_PAGE_COUNTER = "page_counter" +ATTR_PF_KIT_1_REMAINING_LIFE = "pf_kit_1_remaining_life" +ATTR_PF_KIT_MP_REMAINING_LIFE = "pf_kit_mp_remaining_life" +ATTR_STATUS = "status" +ATTR_UNIT = "unit" +ATTR_UPTIME = "uptime" +ATTR_YELLOW_INK_REMAINING = "yellow_ink_remaining" +ATTR_YELLOW_TONER_REMAINING = "yellow_toner_remaining" + +DOMAIN = "brother" + +UNIT_PAGES = "p" +UNIT_DAYS = "days" +UNIT_PERCENT = "%" + +PRINTER_TYPES = ["laser", "ink"] + +SENSOR_TYPES = { + ATTR_STATUS: { + ATTR_ICON: "icon:mdi:printer", + ATTR_LABEL: ATTR_STATUS.title(), + ATTR_UNIT: None, + }, + ATTR_PAGE_COUNTER: { + ATTR_ICON: "mdi:file-document-outline", + ATTR_LABEL: ATTR_PAGE_COUNTER.replace("_", " ").title(), + ATTR_UNIT: UNIT_PAGES, + }, + ATTR_BW_COUNTER: { + ATTR_ICON: "mdi:file-document-outline", + ATTR_LABEL: ATTR_BW_COUNTER.replace("_", " ").title(), + ATTR_UNIT: UNIT_PAGES, + }, + ATTR_COLOR_COUNTER: { + ATTR_ICON: "mdi:file-document-outline", + ATTR_LABEL: ATTR_COLOR_COUNTER.replace("_", " ").title(), + ATTR_UNIT: UNIT_PAGES, + }, + ATTR_DRUM_REMAINING_LIFE: { + ATTR_ICON: "mdi:chart-donut", + ATTR_LABEL: ATTR_DRUM_REMAINING_LIFE.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_BELT_UNIT_REMAINING_LIFE: { + ATTR_ICON: "mdi:current-ac", + ATTR_LABEL: ATTR_BELT_UNIT_REMAINING_LIFE.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_FUSER_REMAINING_LIFE: { + ATTR_ICON: "mdi:water-outline", + ATTR_LABEL: ATTR_FUSER_REMAINING_LIFE.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_LASER_REMAINING_LIFE: { + ATTR_ICON: "mdi:spotlight-beam", + ATTR_LABEL: ATTR_LASER_REMAINING_LIFE.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_PF_KIT_1_REMAINING_LIFE: { + ATTR_ICON: "mdi:printer-3d", + ATTR_LABEL: ATTR_PF_KIT_1_REMAINING_LIFE.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_PF_KIT_MP_REMAINING_LIFE: { + ATTR_ICON: "mdi:printer-3d", + ATTR_LABEL: ATTR_PF_KIT_MP_REMAINING_LIFE.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_BLACK_TONER_REMAINING: { + ATTR_ICON: "mdi:printer-3d-nozzle", + ATTR_LABEL: ATTR_BLACK_TONER_REMAINING.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_CYAN_TONER_REMAINING: { + ATTR_ICON: "mdi:printer-3d-nozzle", + ATTR_LABEL: ATTR_CYAN_TONER_REMAINING.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_MAGENTA_TONER_REMAINING: { + ATTR_ICON: "mdi:printer-3d-nozzle", + ATTR_LABEL: ATTR_MAGENTA_TONER_REMAINING.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_YELLOW_TONER_REMAINING: { + ATTR_ICON: "mdi:printer-3d-nozzle", + ATTR_LABEL: ATTR_YELLOW_TONER_REMAINING.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_BLACK_INK_REMAINING: { + ATTR_ICON: "mdi:printer-3d-nozzle", + ATTR_LABEL: ATTR_BLACK_INK_REMAINING.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_CYAN_INK_REMAINING: { + ATTR_ICON: "mdi:printer-3d-nozzle", + ATTR_LABEL: ATTR_CYAN_INK_REMAINING.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_MAGENTA_INK_REMAINING: { + ATTR_ICON: "mdi:printer-3d-nozzle", + ATTR_LABEL: ATTR_MAGENTA_INK_REMAINING.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_YELLOW_INK_REMAINING: { + ATTR_ICON: "mdi:printer-3d-nozzle", + ATTR_LABEL: ATTR_YELLOW_INK_REMAINING.replace("_", " ").title(), + ATTR_UNIT: UNIT_PERCENT, + }, + ATTR_UPTIME: { + ATTR_ICON: "mdi:timer", + ATTR_LABEL: ATTR_UPTIME.title(), + ATTR_UNIT: UNIT_DAYS, + }, +} diff --git a/homeassistant/components/brother/manifest.json b/homeassistant/components/brother/manifest.json new file mode 100644 index 00000000000..d080ee4fd6c --- /dev/null +++ b/homeassistant/components/brother/manifest.json @@ -0,0 +1,9 @@ +{ + "domain": "brother", + "name": "Brother Printer", + "documentation": "https://www.home-assistant.io/integrations/brother", + "dependencies": [], + "codeowners": ["@bieniu"], + "requirements": ["brother==0.1.4"], + "config_flow": true +} diff --git a/homeassistant/components/brother/sensor.py b/homeassistant/components/brother/sensor.py new file mode 100644 index 00000000000..9ad075f81cd --- /dev/null +++ b/homeassistant/components/brother/sensor.py @@ -0,0 +1,104 @@ +"""Support for the Brother service.""" +import logging + +from homeassistant.helpers.entity import Entity + +from .const import ( + ATTR_DRUM_COUNTER, + ATTR_DRUM_REMAINING_LIFE, + ATTR_DRUM_REMAINING_PAGES, + ATTR_ICON, + ATTR_LABEL, + ATTR_MANUFACTURER, + ATTR_UNIT, + DOMAIN, + SENSOR_TYPES, +) + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_entry(hass, config_entry, async_add_entities): + """Add Brother entities from a config_entry.""" + brother = hass.data[DOMAIN][config_entry.entry_id] + + sensors = [] + + name = brother.model + device_info = { + "identifiers": {(DOMAIN, brother.serial)}, + "name": brother.model, + "manufacturer": ATTR_MANUFACTURER, + "model": brother.model, + "sw_version": brother.firmware, + } + + for sensor in SENSOR_TYPES: + if sensor in brother.data: + sensors.append(BrotherPrinterSensor(brother, name, sensor, device_info)) + async_add_entities(sensors, True) + + +class BrotherPrinterSensor(Entity): + """Define an Brother Printer sensor.""" + + def __init__(self, printer, name, kind, device_info): + """Initialize.""" + self.printer = printer + self._name = name + self._device_info = device_info + self._unique_id = f"{self.printer.serial.lower()}_{kind}" + self.kind = kind + self._state = None + self._attrs = {} + + @property + def name(self): + """Return the name.""" + return f"{self._name} {SENSOR_TYPES[self.kind][ATTR_LABEL]}" + + @property + def state(self): + """Return the state.""" + return self._state + + @property + def device_state_attributes(self): + """Return the state attributes.""" + if self.kind == ATTR_DRUM_REMAINING_LIFE: + self._attrs["remaining_pages"] = self.printer.data.get( + ATTR_DRUM_REMAINING_PAGES + ) + self._attrs["counter"] = self.printer.data.get(ATTR_DRUM_COUNTER) + return self._attrs + + @property + def icon(self): + """Return the icon.""" + return SENSOR_TYPES[self.kind][ATTR_ICON] + + @property + def unique_id(self): + """Return a unique_id for this entity.""" + return self._unique_id + + @property + def unit_of_measurement(self): + """Return the unit the value is expressed in.""" + return SENSOR_TYPES[self.kind][ATTR_UNIT] + + @property + def available(self): + """Return True if entity is available.""" + return self.printer.available + + @property + def device_info(self): + """Return the device info.""" + return self._device_info + + async def async_update(self): + """Update the data from printer.""" + await self.printer.async_update() + + self._state = self.printer.data.get(self.kind) diff --git a/homeassistant/components/brother/strings.json b/homeassistant/components/brother/strings.json new file mode 100644 index 00000000000..a0e43e0e85a --- /dev/null +++ b/homeassistant/components/brother/strings.json @@ -0,0 +1,23 @@ +{ + "config": { + "title": "Brother Printer", + "step": { + "user": { + "title": "Brother Printer", + "description": "Set up Brother printer integration. If you have problems with configuration go to: https://www.home-assistant.io/integrations/brother", + "data": { + "host": "Printer hostname or IP address", + "type": "Type of the printer" + } + } + }, + "error": { + "wrong_host": "Invalid hostname or IP address.", + "connection_error": "Connection error.", + "snmp_error": "SNMP server turned off or printer not supported." + }, + "abort": { + "unsupported_model": "This printer model is not supported." + } + } +} diff --git a/homeassistant/generated/config_flows.py b/homeassistant/generated/config_flows.py index d2a145d15b3..6f3f0e714f6 100644 --- a/homeassistant/generated/config_flows.py +++ b/homeassistant/generated/config_flows.py @@ -13,6 +13,7 @@ FLOWS = [ "ambiclimate", "ambient_station", "axis", + "brother", "cast", "cert_expiry", "coolmaster", diff --git a/requirements_all.txt b/requirements_all.txt index 0990f5848cc..b82561c44e9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -339,6 +339,9 @@ braviarc-homeassistant==0.3.7.dev0 # homeassistant.components.broadlink broadlink==0.12.0 +# homeassistant.components.brother +brother==0.1.4 + # homeassistant.components.brottsplatskartan brottsplatskartan==0.0.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 287629c4adf..904322fe954 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -120,6 +120,9 @@ bomradarloop==0.1.3 # homeassistant.components.broadlink broadlink==0.12.0 +# homeassistant.components.brother +brother==0.1.4 + # homeassistant.components.buienradar buienradar==1.0.1 diff --git a/tests/components/brother/__init__.py b/tests/components/brother/__init__.py new file mode 100644 index 00000000000..91a7b7e92d4 --- /dev/null +++ b/tests/components/brother/__init__.py @@ -0,0 +1 @@ +"""Tests for Brother Printer.""" diff --git a/tests/components/brother/test_config_flow.py b/tests/components/brother/test_config_flow.py new file mode 100644 index 00000000000..5f81be7c1ea --- /dev/null +++ b/tests/components/brother/test_config_flow.py @@ -0,0 +1,127 @@ +"""Define tests for the Brother Printer config flow.""" +import json + +from asynctest import patch +from brother import SnmpError, UnsupportedModel + +from homeassistant import data_entry_flow +from homeassistant.components.brother import config_flow +from homeassistant.components.brother.const import DOMAIN +from homeassistant.const import CONF_HOST, CONF_NAME, CONF_TYPE + +from tests.common import load_fixture + +CONFIG = { + CONF_HOST: "localhost", + CONF_NAME: "Printer", + CONF_TYPE: "laser", +} + + +async def test_show_form(hass): + """Test that the form is served with no input.""" + flow = config_flow.BrotherConfigFlow() + flow.hass = hass + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": "user"} + ) + + assert result["type"] == data_entry_flow.RESULT_TYPE_FORM + assert result["step_id"] == "user" + + +async def test_create_entry_with_hostname(hass): + """Test that the user step works with printer hostname.""" + with patch( + "brother.Brother._get_data", + return_value=json.loads(load_fixture("brother_printer_data.json")), + ): + flow = config_flow.BrotherConfigFlow() + flow.hass = hass + flow.context = {} + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": "user"}, data=CONFIG + ) + + assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY + assert result["title"] == "HL-L2340DW 0123456789" + assert result["data"][CONF_HOST] == CONFIG[CONF_HOST] + assert result["data"][CONF_NAME] == CONFIG[CONF_NAME] + + +async def test_create_entry_with_ip_address(hass): + """Test that the user step works with printer IP address.""" + with patch( + "brother.Brother._get_data", + return_value=json.loads(load_fixture("brother_printer_data.json")), + ): + flow = config_flow.BrotherConfigFlow() + flow.hass = hass + flow.context = {} + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": "user"}, + data={CONF_NAME: "Name", CONF_HOST: "127.0.0.1", CONF_TYPE: "laser"}, + ) + + assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY + assert result["title"] == "HL-L2340DW 0123456789" + assert result["data"][CONF_HOST] == "127.0.0.1" + assert result["data"][CONF_NAME] == "Name" + + +async def test_invalid_hostname(hass): + """Test invalid hostname in user_input.""" + flow = config_flow.BrotherConfigFlow() + flow.hass = hass + + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": "user"}, + data={CONF_NAME: "Name", CONF_HOST: "invalid/hostname", CONF_TYPE: "laser"}, + ) + + assert result["errors"] == {CONF_HOST: "wrong_host"} + + +async def test_connection_error(hass): + """Test connection to host error.""" + with patch("brother.Brother._get_data", side_effect=ConnectionError()): + flow = config_flow.BrotherConfigFlow() + flow.hass = hass + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": "user"}, data=CONFIG + ) + + assert result["errors"] == {"base": "connection_error"} + + +async def test_snmp_error(hass): + """Test SNMP error.""" + with patch("brother.Brother._get_data", side_effect=SnmpError("error")): + flow = config_flow.BrotherConfigFlow() + flow.hass = hass + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": "user"}, data=CONFIG + ) + + assert result["errors"] == {"base": "snmp_error"} + + +async def test_unsupported_model_error(hass): + """Test unsupported printer model error.""" + with patch("brother.Brother._get_data", side_effect=UnsupportedModel("error")): + flow = config_flow.BrotherConfigFlow() + flow.hass = hass + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": "user"}, data=CONFIG + ) + + assert result["type"] == "abort" + assert result["reason"] == "unsupported_model" diff --git a/tests/fixtures/brother_printer_data.json b/tests/fixtures/brother_printer_data.json new file mode 100644 index 00000000000..977953dd3bd --- /dev/null +++ b/tests/fixtures/brother_printer_data.json @@ -0,0 +1,17 @@ +{ + "1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.10.0": ["000104000003da"], + "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": [ + "63010400000001", + "110104000003da", + "410104000023f0", + "31010400000001", + "6f010400001d4c", + "81010400000050", + "8601040000000a" + ], + "1.3.6.1.4.1.2435.2.4.3.2435.5.13.3.0": "Brother HL-L2340DW", + "1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.11.0": ["82010400002b06"], + "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 " + } \ No newline at end of file