Skip to content

Commit

Permalink
Errors when off (#394)
Browse files Browse the repository at this point in the history
* throw PlatformNotReady when printer is not reachable

* tweak testing

* add tests
  • Loading branch information
marcolivierarsenault authored Aug 27, 2024
1 parent 23596ca commit d116c86
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 20 deletions.
40 changes: 28 additions & 12 deletions custom_components/moonraker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
import os.path
import uuid
from datetime import timedelta
import socket

import async_timeout
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import Config, HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
Expand Down Expand Up @@ -54,6 +55,17 @@ def get_user_name(hass: HomeAssistant, entry: ConfigEntry):
return device_entries[0].name_by_user


def is_open(ip, port):
"""Check if port is open."""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, int(port)))
s.shutdown(2)
return True
except Exception:
return False


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Set up this integration using UI."""

Expand Down Expand Up @@ -87,20 +99,24 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):

try:
async with async_timeout.timeout(TIMEOUT):
await api.start()
printer_info = await api.client.call_method("printer.info")
_LOGGER.debug(printer_info)
if is_open(url, port):
await api.start()
printer_info = await api.client.call_method("printer.info")
_LOGGER.debug(printer_info)

if printer_name == "":
api_device_name = printer_info[HOSTNAME]
else:
api_device_name = printer_name
if printer_name == "":
api_device_name = printer_info[HOSTNAME]
else:
api_device_name = printer_name

hass.config_entries.async_update_entry(entry, title=api_device_name)
hass.config_entries.async_update_entry(entry, title=api_device_name)
else:
_LOGGER.warning("Cannot connect to moonraker instance")
raise PlatformNotReady(f"Error connecting to {url}:{port}")

except Exception as exc:
except Exception:
_LOGGER.warning("Cannot configure moonraker instance")
raise ConfigEntryNotReady(f"Error connecting to {url}:{port}") from exc
raise PlatformNotReady(f"Error connecting to {url}:{port}")

coordinator = MoonrakerDataUpdateCoordinator(
hass, client=api, config_entry=entry, api_device_name=api_device_name
Expand All @@ -109,7 +125,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
await coordinator.async_refresh()

if not coordinator.last_update_success:
raise ConfigEntryNotReady
raise PlatformNotReady

hass.data[DOMAIN][entry.entry_id] = coordinator
for platform in PLATFORMS:
Expand Down
9 changes: 9 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,12 @@ def get_moonraker_default_mock(get_default_api_response):
return_value=get_default_api_response,
):
yield


@pytest.fixture(name="skip_connection_check")
def skip_connection_check_fixture():
"""Skip skip_connection_check ."""
with (
patch("custom_components.moonraker.is_open"),
):
yield
6 changes: 6 additions & 0 deletions tests/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ def bypass_connect_client_fixture():
yield


@pytest.fixture(name="bypass_connection_test", autouse=True)
def bypass_connection_test_fixture(skip_connection_check):
"""Skip calls to get data from API."""
yield


async def test_runout_filament_sensor_missing(hass, get_data, get_printer_objects_list):
"""Test."""
get_data["status"].pop("filament_switch_sensor filament_sensor_1", None)
Expand Down
6 changes: 6 additions & 0 deletions tests/test_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ def bypass_connect_client_fixture():
yield


@pytest.fixture(name="bypass_connection_test", autouse=True)
def bypass_connection_test_fixture(skip_connection_check):
"""Skip calls to get data from API."""
yield


@pytest.mark.parametrize(
"button, method",
[
Expand Down
6 changes: 6 additions & 0 deletions tests/test_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ def bypass_connect_client_fixture():
yield


@pytest.fixture(name="bypass_connection_test", autouse=True)
def bypass_connection_test_fixture(skip_connection_check):
"""Skip calls to get data from API."""
yield


async def test_camera_services(hass, caplog):
"""Test camera services."""

Expand Down
6 changes: 6 additions & 0 deletions tests/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
from .const import MOCK_CONFIG, MOCK_OPTIONS


@pytest.fixture(name="bypass_connection_test", autouse=True)
def bypass_connection_test_fixture(skip_connection_check):
"""Skip calls to get data from API."""
yield


@pytest.fixture(name="bypass_connect_client")
def bypass_connect_client_fixture():
"""Skip calls to get data from API."""
Expand Down
41 changes: 33 additions & 8 deletions tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from unittest.mock import patch

import pytest
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers.update_coordinator import UpdateFailed
from pytest_homeassistant_custom_component.common import MockConfigEntry

Expand All @@ -25,7 +25,13 @@ def bypass_connect_client_fixture():
yield


async def test_setup_unload_and_reload_entry(hass):
@pytest.fixture(name="bypass_connection_test")
def bypass_connection_test_fixture(skip_connection_check):
"""Skip calls to get data from API."""
yield


async def test_setup_unload_and_reload_entry(hass, bypass_connection_test):
"""Test entry setup and unload."""
# Create a mock entry so we don't have to go through config flow

Expand All @@ -51,7 +57,7 @@ async def test_setup_unload_and_reload_entry(hass):
assert config_entry.entry_id not in hass.data[DOMAIN]


async def test_setup_unload_and_reload_entry_with_name(hass):
async def test_setup_unload_and_reload_entry_with_name(hass, bypass_connection_test):
"""Test entry setup with name and unload."""
# Create a mock entry so we don't have to go through config flow

Expand Down Expand Up @@ -79,7 +85,7 @@ async def test_setup_unload_and_reload_entry_with_name(hass):
assert config_entry.entry_id not in hass.data[DOMAIN]


async def test_async_send_data_exception(hass):
async def test_async_send_data_exception(hass, bypass_connection_test):
"""Test async_post_exception."""

config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, entry_id="test")
Expand All @@ -100,7 +106,7 @@ async def test_async_send_data_exception(hass):
assert await async_unload_entry(hass, config_entry)


async def test_setup_entry_exception(hass):
async def test_setup_entry_exception(hass, bypass_connection_test):
"""Test ConfigEntryNotReady when API raises an exception during entry setup."""
with patch(
"moonraker_api.MoonrakerClient.call_method",
Expand All @@ -109,7 +115,7 @@ async def test_setup_entry_exception(hass):
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, entry_id="test")
config_entry.add_to_hass(hass)

with pytest.raises(ConfigEntryNotReady):
with pytest.raises(PlatformNotReady):
assert await async_setup_entry(hass, config_entry)


Expand All @@ -121,7 +127,7 @@ def load_data(endpoint, *args, **kwargs):
raise Exception


async def test_failed_first_refresh(hass):
async def test_failed_first_refresh(hass, bypass_connection_test):
"""Test ConfigEntryNotReady when API raises an exception during entry setup."""
with patch(
"moonraker_api.MoonrakerClient.call_method",
Expand All @@ -130,5 +136,24 @@ async def test_failed_first_refresh(hass):
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, entry_id="test")
config_entry.add_to_hass(hass)

with pytest.raises(ConfigEntryNotReady):
with pytest.raises(PlatformNotReady):
assert await async_setup_entry(hass, config_entry)


async def test_is_on(hass):
"""Test connection is working."""
with patch("socket.socket"):
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, entry_id="test")
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()


async def test_is_off(hass):
"""Test connection is working."""
with patch("socket.socket", side_effect=Exception("mocked error")):
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, entry_id="test")
config_entry.add_to_hass(hass)

with pytest.raises(PlatformNotReady):
assert await async_setup_entry(hass, config_entry)
6 changes: 6 additions & 0 deletions tests/test_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ def bypass_connect_client_fixture():
yield


@pytest.fixture(name="bypass_connection_test", autouse=True)
def bypass_connection_test_fixture(skip_connection_check):
"""Skip calls to get data from API."""
yield


# test number
@pytest.mark.parametrize(
"number",
Expand Down
6 changes: 6 additions & 0 deletions tests/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ def bypass_connect_client_fixture():
yield


@pytest.fixture(name="bypass_connection_test", autouse=True)
def bypass_connection_test_fixture(skip_connection_check):
"""Skip calls to get data from API."""
yield


@pytest.fixture(name="data_for_calculate_pct")
def data_for_calculate_pct_fixture():
"""data_for_calculate_pct."""
Expand Down
6 changes: 6 additions & 0 deletions tests/test_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ def bypass_connect_client_fixture():
yield


@pytest.fixture(name="bypass_connection_test", autouse=True)
def bypass_connection_test_fixture(skip_connection_check):
"""Skip calls to get data from API."""
yield


# test switches
@pytest.mark.parametrize(
"switch, switch_type",
Expand Down

0 comments on commit d116c86

Please sign in to comment.