diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index ba7eb1a7..750fba04 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -27,10 +27,26 @@ jobs: - python-version: "3.10" core-version: "2023.4.6" - python-version: "3.10" - core-version: "2023.5.2" + core-version: "2023.5.4" - python-version: "3.11" - core-version: "2023.6.1" + core-version: "2023.6.3" - python-version: "3.11" + core-version: "2023.7.3" + - python-version: "3.11" + core-version: "2023.8.4" + - python-version: "3.11" + core-version: "2023.9.3" + - python-version: "3.11" + core-version: "2023.10.5" + - python-version: "3.11" + core-version: "2023.11.3" + - python-version: "3.11" + core-version: "2023.12.4" + - python-version: "3.11" + core-version: "2024.1.6" + - python-version: "3.11" + core-version: "2024.2.5" + - python-version: "3.12" core-version: "dev" steps: - name: Check out code from GitHub @@ -56,6 +72,11 @@ jobs: run: | cd core + # Link homeassitant.components.adaptive_lighting + cd homeassistant/components + ln -fs ../../../custom_components/adaptive_lighting adaptive_lighting + cd - + # Link adaptive_lighting tests cd tests/components/ ln -fs ../../../tests adaptive_lighting @@ -71,10 +92,8 @@ jobs: -qq \ --timeout=9 \ --durations=10 \ - --cov="custom_components.adaptive_lighting" \ + --cov="homeassistant" \ --cov-report=xml \ -o console_output_style=count \ -p no:sugar \ tests/components/adaptive_lighting - env: - HA_CLONE: true diff --git a/Dockerfile b/Dockerfile index 4baac59a..916d1021 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,8 @@ RUN pip3 install -r /core/requirements.txt --use-pep517 && \ COPY . /app/ # Setup symlinks in core -RUN ln -s /app/tests /core/tests/components/adaptive_lighting && \ +RUN ln -s /app/custom_components/adaptive_lighting /core/homeassistant/components/adaptive_lighting && \ + ln -s /app/tests /core/tests/components/adaptive_lighting && \ # For test_dependencies.py ln -s /core /app/core @@ -38,8 +39,6 @@ WORKDIR /core # Make 'custom_components/adaptive_lighting' imports available to tests ENV PYTHONPATH="${PYTHONPATH}:/app" -# Enable testing against HA clone (instead of pytest_homeassistant_custom_component) -ENV HA_CLONE=true ENTRYPOINT ["python3", \ # Enable Python development mode @@ -53,7 +52,7 @@ ENTRYPOINT ["python3", \ # Print the 10 slowest tests "--durations=10", \ # Measure code coverage for the 'homeassistant' package - "--cov=custom_components.adaptive_lighting", \ + "--cov='homeassistant'", \ # Generate an XML report of the code coverage "--cov-report=xml", \ # Generate an HTML report of the code coverage diff --git a/test_dependencies.py b/test_dependencies.py index a07f9ee6..96377cee 100644 --- a/test_dependencies.py +++ b/test_dependencies.py @@ -36,6 +36,7 @@ required = [ "components.stream", "components.conversation", # only available after HA≥2023.2 "components.cloud", + "components.ffmpeg", # needed since 2024.1 ] to_install = [package for r in required for package in deps[r]] diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 79b83fb6..00000000 --- a/tests/conftest.py +++ /dev/null @@ -1,20 +0,0 @@ -"""Fixtures for testing.""" - -import os -import sys - -import pytest - -# Tests in the dev enviromentment use the pytest_homeassistant_custom_component instead of -# a cloned HA core repo for a simple and clean structure. To still test against a HA core -# clone (e.g. the dev branch for which no pytest_homeassistant_custom_component exists -# because HA does not publish dev snapshot packages), set the HA_CLONE env variable. -if "HA_CLONE" in os.environ: - # Rewire the testing package to the cloned test modules. See the test `Dockerfile` - # for setup details. - sys.modules["pytest_homeassistant_custom_component"] = __import__("tests") - - -@pytest.fixture(autouse=True) -def auto_enable_custom_integrations(enable_custom_integrations): - return diff --git a/tests/test_adaptation_utils.py b/tests/test_adaptation_utils.py index 8e36a181..10774fa2 100644 --- a/tests/test_adaptation_utils.py +++ b/tests/test_adaptation_utils.py @@ -3,15 +3,7 @@ from unittest.mock import Mock import pytest -from homeassistant.components.light import ( - ATTR_BRIGHTNESS, - ATTR_COLOR_TEMP_KELVIN, - ATTR_TRANSITION, -) -from homeassistant.const import ATTR_ENTITY_ID, STATE_ON -from homeassistant.core import Context, State - -from custom_components.adaptive_lighting.adaptation_utils import ( +from homeassistant.components.adaptive_lighting.adaptation_utils import ( ServiceData, _create_service_call_data_iterator, _has_relevant_service_data_attributes, @@ -19,6 +11,13 @@ from custom_components.adaptive_lighting.adaptation_utils import ( _split_service_call_data, prepare_adaptation_data, ) +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, + ATTR_COLOR_TEMP_KELVIN, + ATTR_TRANSITION, +) +from homeassistant.const import ATTR_ENTITY_ID, STATE_ON +from homeassistant.core import Context, State @pytest.mark.parametrize( @@ -130,7 +129,7 @@ async def test_has_relevant_service_data_attributes( service_data: ServiceData, expected_relevant: bool, ): - """Test the determination of relevancy of service data""" + """Test the determination of relevancy of service data.""" assert _has_relevant_service_data_attributes(service_data) == expected_relevant diff --git a/tests/test_color_and_brightness.py b/tests/test_color_and_brightness.py index b8398a71..6c76175f 100644 --- a/tests/test_color_and_brightness.py +++ b/tests/test_color_and_brightness.py @@ -4,8 +4,7 @@ import zoneinfo import pytest from astral import LocationInfo from astral.location import Location - -from custom_components.adaptive_lighting.color_and_brightness import ( +from homeassistant.components.adaptive_lighting.color_and_brightness import ( SUN_EVENT_NOON, SUN_EVENT_SUNRISE, SunEvents, diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py index 1678e3d4..1a9e8fbf 100644 --- a/tests/test_config_flow.py +++ b/tests/test_config_flow.py @@ -1,11 +1,7 @@ """Test Adaptive Lighting config flow.""" from homeassistant import data_entry_flow -from homeassistant.config_entries import SOURCE_IMPORT -from homeassistant.const import CONF_NAME -from pytest_homeassistant_custom_component.common import MockConfigEntry - -from custom_components.adaptive_lighting.const import ( +from homeassistant.components.adaptive_lighting.const import ( CONF_SUNRISE_TIME, CONF_SUNSET_TIME, DEFAULT_NAME, @@ -13,6 +9,10 @@ from custom_components.adaptive_lighting.const import ( NONE_STR, VALIDATION_TUPLES, ) +from homeassistant.config_entries import SOURCE_IMPORT +from homeassistant.const import CONF_NAME + +from tests.common import MockConfigEntry DEFAULT_DATA = {key: default for key, default, _ in VALIDATION_TUPLES} diff --git a/tests/test_hass_utils.py b/tests/test_hass_utils.py index 9f044d8a..4be4c88d 100644 --- a/tests/test_hass_utils.py +++ b/tests/test_hass_utils.py @@ -2,16 +2,15 @@ from unittest.mock import AsyncMock +from homeassistant.components.adaptive_lighting.adaptation_utils import ServiceData +from homeassistant.components.adaptive_lighting.hass_utils import ( + setup_service_call_interceptor, +) from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN from homeassistant.const import SERVICE_TURN_ON from homeassistant.core import ServiceCall from homeassistant.util.read_only_dict import ReadOnlyDict -from custom_components.adaptive_lighting.adaptation_utils import ServiceData -from custom_components.adaptive_lighting.hass_utils import ( - setup_service_call_interceptor, -) - async def test_setup_service_call_interceptor(hass): """Test setup and removal of service call interceptor.""" diff --git a/tests/test_init.py b/tests/test_init.py index 19710d57..6bbfd599 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -1,12 +1,15 @@ """Tests for Adaptive Lighting integration.""" +from homeassistant.components import adaptive_lighting +from homeassistant.components.adaptive_lighting.const import ( + DEFAULT_NAME, + UNDO_UPDATE_LISTENER, +) from homeassistant.config_entries import ConfigEntryState from homeassistant.const import CONF_NAME from homeassistant.setup import async_setup_component -from pytest_homeassistant_custom_component.common import MockConfigEntry -from custom_components import adaptive_lighting -from custom_components.adaptive_lighting.const import DEFAULT_NAME, UNDO_UPDATE_LISTENER +from tests.common import MockConfigEntry async def test_setup_with_config(hass): diff --git a/tests/test_switch.py b/tests/test_switch.py index 9585c960..9c2f254f 100644 --- a/tests/test_switch.py +++ b/tests/test_switch.py @@ -15,47 +15,14 @@ import homeassistant.util.dt as dt_util import pytest import ulid_transform import voluptuous.error -from homeassistant.components.light import ( - ATTR_BRIGHTNESS, - ATTR_BRIGHTNESS_PCT, - ATTR_COLOR_TEMP_KELVIN, - ATTR_RGB_COLOR, - ATTR_TRANSITION, - ATTR_XY_COLOR, - SERVICE_TURN_OFF, -) -from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN -from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN -from homeassistant.config_entries import ConfigEntryState -from homeassistant.const import ( - ATTR_AREA_ID, - ATTR_ENTITY_ID, - ATTR_SUPPORTED_FEATURES, - CONF_LIGHTS, - CONF_NAME, - EVENT_CALL_SERVICE, - EVENT_STATE_CHANGED, - SERVICE_TOGGLE, - SERVICE_TURN_ON, - STATE_OFF, - STATE_ON, -) -from homeassistant.core import Context, Event, HomeAssistant, State -from homeassistant.helpers import entity_registry -from homeassistant.helpers.entity_platform import async_get_platforms -from homeassistant.setup import async_setup_component -from homeassistant.util.color import color_temperature_mired_to_kelvin -from pytest_homeassistant_custom_component.common import ( - MockConfigEntry, - mock_area_registry, -) - -from custom_components.adaptive_lighting.adaptation_utils import ( +from homeassistant.components.adaptive_lighting.adaptation_utils import ( AdaptationData, _create_service_call_data_iterator, ) -from custom_components.adaptive_lighting.color_and_brightness import lerp_color_hsv -from custom_components.adaptive_lighting.const import ( +from homeassistant.components.adaptive_lighting.color_and_brightness import ( + lerp_color_hsv, +) +from homeassistant.components.adaptive_lighting.const import ( ADAPT_BRIGHTNESS_SWITCH, ADAPT_COLOR_SWITCH, ATTR_ADAPTIVE_LIGHTING_MANAGER, @@ -93,7 +60,7 @@ from custom_components.adaptive_lighting.const import ( SLEEP_MODE_SWITCH, UNDO_UPDATE_LISTENER, ) -from custom_components.adaptive_lighting.switch import ( +from homeassistant.components.adaptive_lighting.switch import ( CONF_INTERCEPT, AdaptiveLightingManager, AdaptiveSwitch, @@ -103,6 +70,39 @@ from custom_components.adaptive_lighting.switch import ( is_our_context, is_our_context_id, ) +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, + ATTR_BRIGHTNESS_PCT, + ATTR_COLOR_TEMP_KELVIN, + ATTR_RGB_COLOR, + ATTR_TRANSITION, + ATTR_XY_COLOR, + SERVICE_TURN_OFF, +) +from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN +from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN +from homeassistant.components.template.light import LightTemplate +from homeassistant.config_entries import ConfigEntryState +from homeassistant.const import ( + ATTR_AREA_ID, + ATTR_ENTITY_ID, + ATTR_SUPPORTED_FEATURES, + CONF_LIGHTS, + CONF_NAME, + EVENT_CALL_SERVICE, + EVENT_STATE_CHANGED, + SERVICE_TOGGLE, + SERVICE_TURN_ON, + STATE_OFF, + STATE_ON, +) +from homeassistant.core import Context, Event, HomeAssistant, State +from homeassistant.helpers import entity_registry +from homeassistant.helpers.entity_platform import async_get_platforms +from homeassistant.setup import async_setup_component +from homeassistant.util.color import color_temperature_mired_to_kelvin + +from tests.common import MockConfigEntry, mock_area_registry _LOGGER = logging.getLogger(__name__) @@ -234,7 +234,11 @@ async def setup_lights(hass: HomeAssistant, with_group: bool = False): return lights -async def setup_lights_and_switch(hass, extra_conf=None, all_lights: bool = False): +async def setup_lights_and_switch( + hass, + extra_conf=None, + all_lights: bool = False, +) -> tuple[AdaptiveSwitch, list[LightTemplate]]: """Create switch and demo lights.""" # Setup demo lights and turn on lights_instances = await setup_lights(hass) @@ -411,7 +415,7 @@ async def test_adaptive_lighting_time_zones_and_sun_settings( async def patch_time_and_update(time): with patch( - "custom_components.adaptive_lighting.color_and_brightness.utcnow", + "homeassistant.components.adaptive_lighting.color_and_brightness.utcnow", return_value=time, ): await switch._update_attrs_and_maybe_adapt_lights(context=context) @@ -503,7 +507,7 @@ async def test_light_settings(hass): async def patch_time_and_get_updated_states(time): with patch( - "custom_components.adaptive_lighting.color_and_brightness.utcnow", + "homeassistant.components.adaptive_lighting.color_and_brightness.utcnow", return_value=time, ): await switch._update_attrs_and_maybe_adapt_lights( @@ -1324,7 +1328,7 @@ async def test_separate_turn_on_commands(hass, separate_turn_on_commands): assert sleep_color_temp != color_temp -async def test_area(hass): +async def test_light_switch_in_specific_area(hass): switch, (light, *_) = await setup_lights_and_switch(hass) area_registry = mock_area_registry(hass) @@ -1611,7 +1615,6 @@ async def test_proactive_adaptation_transition_override(hass): }, True, ) - with patch.object( light3, "async_turn_on", @@ -1632,6 +1635,7 @@ async def test_proactive_adaptation_transition_override(hass): ) # Assert that default is used when no transition is specified in service call + assert patched_async_turn_on.call_args_list, patched_async_turn_on.call_args_list kwargs = patched_async_turn_on.call_args_list[0].kwargs assert set({ATTR_TRANSITION: 123}.items()).issubset(kwargs.items()) @@ -1815,7 +1819,7 @@ async def test_two_switches_for_single_light(hass): extra_conf | {CONF_NAME: "switch2"}, all_lights=True, ) - assert light1 is light2 + assert light1.entity_id == light2.entity_id # One switch controls brightness the other color await switch1.adapt_color_switch.async_turn_off() @@ -1897,7 +1901,7 @@ async def test_adapt_until_sleep_and_rgb_colors(hass): async def patch_time_and_update(time): with patch( - "custom_components.adaptive_lighting.color_and_brightness.utcnow", + "homeassistant.components.adaptive_lighting.color_and_brightness.utcnow", return_value=time, ): await switch._update_attrs_and_maybe_adapt_lights(context=context) @@ -2160,7 +2164,7 @@ async def test_brightness_mode(hass, brightness_mode, dark, light): async def patch_time_and_update(time): with patch( - "custom_components.adaptive_lighting.color_and_brightness.utcnow", + "homeassistant.components.adaptive_lighting.color_and_brightness.utcnow", return_value=time, ): await switch._update_attrs_and_maybe_adapt_lights(context=context)