Skip to content

Commit

Permalink
Add binary sensor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pnbruckner committed Mar 9, 2024
1 parent 060cf6d commit 98a670a
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 56 deletions.
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
asyncio_mode = "auto"
testpaths = ["tests"]
norecursedirs = [".git"]
log_format = "%(asctime)s.%(msecs)03d %(levelname)-8s %(threadName)s %(name)s:%(filename)s:%(lineno)s %(message)s"
log_date_format = "%Y-%m-%d %H:%M:%S"
36 changes: 36 additions & 0 deletions tests/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Test constants."""

HOME_CONFIG = {"unique_id": "home"}

NY_LOC = {
"latitude": 40.68954412564642,
"longitude": -74.04486696480146,
"elevation": 0,
"time_zone": "America/New_York",
}
NY_CONFIG = {
"unique_id": "new_york",
"location": "Statue of Liberty",
} | NY_LOC

TWINE_LOC = {
"latitude": 39.50924426436838,
"longitude": -98.43369506033378,
"elevation": 10,
"time_zone": "America/Chicago",
}
TWINE_CONFIG = {
"unique_id": "twine",
"location": "World's Largest Ball of Twine",
} | TWINE_LOC

HW_LOC = {
"latitude": 34.134092337996336,
"longitude": -118.32154780135669,
"elevation": 391,
"time_zone": "America/Los_Angeles",
}
HW_CONFIG = {
"unique_id": "hollywood",
"location": "Hollywood Sign",
} | HW_LOC
87 changes: 87 additions & 0 deletions tests/test_binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""Test binary_sensor module."""
from __future__ import annotations

from datetime import datetime, time, timedelta
from unittest.mock import patch
import pytest

from pytest_homeassistant_custom_component.common import (
async_fire_time_changed,
assert_setup_component,
)

from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_registry import EntityRegistry
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util, slugify

from custom_components.sun2.const import DOMAIN

from .const import NY_CONFIG


@pytest.mark.parametrize(
"elevation,name,slug",
(
("horizon", None, "above_horizon"),
(1, None, "above_1_0_deg"),
(-1, None, "above_minus_1_0_deg"),
(0, "Name Test", "name_test"),
),
)
async def test_yaml_binary_sensor(
hass: HomeAssistant,
entity_registry: EntityRegistry,
elevation: str | float,
name: str | None,
slug: str,
) -> None:
"""Test YAML configured elevation binary sensor."""
config = NY_CONFIG | {
"binary_sensors": [
{
"unique_id": "bs1",
"elevation": elevation,
}
]
}
if name:
config["binary_sensors"][0]["name"] = name

tz = dt_util.get_time_zone(NY_CONFIG["time_zone"])
base_time = dt_util.now(tz)

# Set time to 00:00:00 tommorow.
now = datetime.combine((base_time + timedelta(1)).date(), time()).replace(tzinfo=tz)

with patch("homeassistant.util.dt.now", return_value=now):
with assert_setup_component(1, DOMAIN):
await async_setup_component(hass, DOMAIN, {DOMAIN: [config]})
await hass.async_block_till_done()

config_entry = hass.config_entries.async_entries(DOMAIN)[0]

# Check that elevation binary_sensor was created with expected entity ID and it has
# the expected state.
entity_id = entity_registry.async_get_entity_id(
"binary_sensor", DOMAIN, f"{config_entry.entry_id}-bs1"
)
expected_id = f"binary_sensor.{slugify(NY_CONFIG['location'])}_sun_{slug}"
assert entity_id == expected_id
state = hass.states.get(entity_id)
# Sun is always below the horizon at midnight in New York.
assert state.state == STATE_OFF
# And is always above the horizon at noon.
# Next change should be after midnight and before noon.
next_change = state.attributes.get("next_change")
noon = now.replace(hour=12)
assert isinstance(next_change, datetime)
assert now < next_change < noon

# Move time to next_change and make sure state has changed.
with patch("homeassistant.util.dt.now", return_value=next_change):
async_fire_time_changed(hass, next_change)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state.state == STATE_ON
76 changes: 20 additions & 56 deletions tests/test_init.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Test init module."""
from __future__ import annotations

from unittest.mock import patch
Expand All @@ -11,48 +12,15 @@

from custom_components.sun2.const import DOMAIN

CONFIG_1 = {"unique_id": "1"}

LOC_2A = {
"latitude": 40.68954412564642,
"longitude": -74.04486696480146,
"elevation": 0,
"time_zone": "America/New_York",
}
CONFIG_2A = {
"unique_id": "Test 2",
"location": "Statue of Liberty",
} | LOC_2A

LOC_2B = {
"latitude": 39.50924426436838,
"longitude": -98.43369506033378,
"elevation": 10,
"time_zone": "America/Chicago",
}
CONFIG_2B = {
"unique_id": "Test 2",
"location": "World's Largest Ball of Twine",
} | LOC_2B

LOC_3 = {
"latitude": 34.134092337996336,
"longitude": -118.32154780135669,
"elevation": 391,
"time_zone": "America/Los_Angeles",
}
CONFIG_3 = {
"unique_id": "3",
"location": "Hollywood Sign",
} | LOC_3
from .const import HOME_CONFIG, HW_CONFIG, HW_LOC, NY_CONFIG, NY_LOC, TWINE_CONFIG, TWINE_LOC


async def test_basic_yaml_config(
hass: HomeAssistant, entity_registry: EntityRegistry
) -> None:
"""Test basic YAML configuration."""
with assert_setup_component(1, DOMAIN):
await async_setup_component(hass, DOMAIN, {DOMAIN: [CONFIG_1]})
await async_setup_component(hass, DOMAIN, {DOMAIN: [HOME_CONFIG]})
await hass.async_block_till_done()

expected_entities = (
Expand Down Expand Up @@ -104,11 +72,9 @@ async def test_basic_yaml_config(
assert entry.disabled != enabled


async def test_reload_service(
hass: HomeAssistant, entity_registry: EntityRegistry
) -> None:
async def test_reload_service(hass: HomeAssistant) -> None:
"""Test basic YAML configuration."""
init_config = [CONFIG_1, CONFIG_2A]
init_config = [HOME_CONFIG, NY_CONFIG]
with assert_setup_component(len(init_config), DOMAIN):
await async_setup_component(hass, DOMAIN, {DOMAIN: init_config})
await hass.async_block_till_done()
Expand All @@ -117,19 +83,19 @@ async def test_reload_service(
config_entries = hass.config_entries.async_entries(DOMAIN)
assert len(config_entries) == 2
config_entry_1 = config_entries[0]
assert config_entry_1.unique_id == CONFIG_1["unique_id"]
assert config_entry_1.unique_id == HOME_CONFIG["unique_id"]
assert config_entry_1.title == hass.config.location_name
assert config_entry_1.options == {}
config_entry_2 = config_entries[1]
assert config_entry_2.unique_id == CONFIG_2A["unique_id"]
assert config_entry_2.title == CONFIG_2A["location"]
assert config_entry_2.options == LOC_2A
assert config_entry_2.unique_id == NY_CONFIG["unique_id"]
assert config_entry_2.title == NY_CONFIG["location"]
assert config_entry_2.options == NY_LOC

# Check reload service exists.
assert hass.services.has_service(DOMAIN, "reload")

# Reload new config.
reload_config = [CONFIG_2B, CONFIG_3]
reload_config = [TWINE_CONFIG, HW_CONFIG]
with patch(
"custom_components.sun2.async_integration_yaml_config",
autospec=True,
Expand All @@ -142,16 +108,16 @@ async def test_reload_service(
config_entries = hass.config_entries.async_entries(DOMAIN)
assert len(config_entries) == 2
config_entry_1 = config_entries[0]
assert config_entry_1.unique_id == CONFIG_2B["unique_id"]
assert config_entry_1.title == CONFIG_2B["location"]
assert config_entry_1.options == LOC_2B
assert config_entry_1.unique_id == TWINE_CONFIG["unique_id"]
assert config_entry_1.title == TWINE_CONFIG["location"]
assert config_entry_1.options == TWINE_LOC
config_entry_2 = config_entries[1]
assert config_entry_2.unique_id == CONFIG_3["unique_id"]
assert config_entry_2.title == CONFIG_3["location"]
assert config_entry_2.options == LOC_3
assert config_entry_2.unique_id == HW_CONFIG["unique_id"]
assert config_entry_2.title == HW_CONFIG["location"]
assert config_entry_2.options == HW_LOC

# Reload with same config.
reload_config = [CONFIG_2B, CONFIG_3]
reload_config = [TWINE_CONFIG, HW_CONFIG]
with patch(
"custom_components.sun2.async_integration_yaml_config",
autospec=True,
Expand Down Expand Up @@ -192,9 +158,7 @@ async def test_reload_service(
assert not hass.config_entries.async_entries(DOMAIN)


async def test_ha_config_update(
hass: HomeAssistant, entity_registry: EntityRegistry
) -> None:
async def test_ha_config_update(hass: HomeAssistant) -> None:
"""Test when HA config is updated."""
new_time_zone = "America/New_York"
new_location_name = "New York, NY"
Expand All @@ -203,7 +167,7 @@ async def test_ha_config_update(
assert hass.config.time_zone != new_time_zone
assert hass.config.location_name != new_location_name

await async_setup_component(hass, DOMAIN, {DOMAIN: [CONFIG_1]})
await async_setup_component(hass, DOMAIN, {DOMAIN: [HOME_CONFIG]})
await hass.async_block_till_done()

# ConfigEntry object may change values, but it should not be replaced by a new
Expand Down Expand Up @@ -237,7 +201,7 @@ async def test_ha_config_update(
with patch(
"custom_components.sun2.async_integration_yaml_config",
autospec=True,
return_value={DOMAIN: [CONFIG_1]},
return_value={DOMAIN: [HOME_CONFIG]},
):
await hass.config.async_update(location_name=new_location_name)
await hass.async_block_till_done()
Expand Down

0 comments on commit 98a670a

Please sign in to comment.