mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-19 10:14:04 +02:00
VS Code Dev Container (dev & test environment) (#605)
* build: dev container
Add a VS Code Dev Container from the blueprint at bceaae212f
* build: dev container test setup
Add support for unit testing in the dev container environment with debugging and code coverage.
* ci: adjust to dev container test restructuring
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* ci: fix coverage collection
* build: add dummy light to HA config
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* build: update dev container to Python 3.11 (for HA 2023.6)
* Add VS Code tasks
* Use pre-commit hooks for linting
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Unpin HA version
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
This commit is contained in:
parent
12dae4b6a6
commit
6283158ff7
18 changed files with 329 additions and 111 deletions
|
|
@ -1,7 +1,7 @@
|
|||
# Developer notes for the tests directory
|
||||
|
||||
To run the tests, check out the [CI configuration](../.github/workflows/pytest.yml) to see how they are executed in the CI pipeline.
|
||||
Alternatively, you can use the provided Docker image to run the tests locally.
|
||||
Alternatively, you can use the provided Docker image to run the tests locally or run them with VS Code directly in the dev container.
|
||||
|
||||
To run the tests using the Docker image, navigate to the `adaptive-lighting` repo folder and execute the following command:
|
||||
|
||||
|
|
|
|||
19
tests/conftest.py
Normal file
19
tests/conftest.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
"""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):
|
||||
yield
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
"""Test Adaptive Lighting config flow."""
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant.components.adaptive_lighting.const import (
|
||||
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 (
|
||||
CONF_SUNRISE_TIME,
|
||||
CONF_SUNSET_TIME,
|
||||
DEFAULT_NAME,
|
||||
|
|
@ -8,10 +12,6 @@ from homeassistant.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}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
"""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 tests.common import MockConfigEntry
|
||||
from custom_components import adaptive_lighting
|
||||
from custom_components.adaptive_lighting.const import DEFAULT_NAME, UNDO_UPDATE_LISTENER
|
||||
|
||||
|
||||
async def test_setup_with_config(hass):
|
||||
|
|
|
|||
|
|
@ -8,7 +8,49 @@ import logging
|
|||
from random import randint
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from homeassistant.components.adaptive_lighting.const import (
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_BRIGHTNESS_PCT,
|
||||
ATTR_COLOR_TEMP_KELVIN,
|
||||
ATTR_MAX_COLOR_TEMP_KELVIN,
|
||||
ATTR_MIN_COLOR_TEMP_KELVIN,
|
||||
ATTR_RGB_COLOR,
|
||||
ATTR_SUPPORTED_COLOR_MODES,
|
||||
ATTR_TRANSITION,
|
||||
ATTR_XY_COLOR,
|
||||
COLOR_MODE_BRIGHTNESS,
|
||||
)
|
||||
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
||||
from homeassistant.components.light import SERVICE_TURN_OFF
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
import homeassistant.config as config_util
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import (
|
||||
ATTR_AREA_ID,
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
CONF_LIGHTS,
|
||||
CONF_NAME,
|
||||
EVENT_STATE_CHANGED,
|
||||
SERVICE_TURN_ON,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import Context, 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
|
||||
import homeassistant.util.dt as dt_util
|
||||
import pytest
|
||||
from pytest_homeassistant_custom_component.common import (
|
||||
MockConfigEntry,
|
||||
mock_area_registry,
|
||||
)
|
||||
import ulid_transform
|
||||
import voluptuous.error
|
||||
|
||||
from custom_components.adaptive_lighting.const import (
|
||||
ADAPT_BRIGHTNESS_SWITCH,
|
||||
ADAPT_COLOR_SWITCH,
|
||||
ATTR_TURN_ON_OFF_LISTENER,
|
||||
|
|
@ -38,7 +80,7 @@ from homeassistant.components.adaptive_lighting.const import (
|
|||
SLEEP_MODE_SWITCH,
|
||||
UNDO_UPDATE_LISTENER,
|
||||
)
|
||||
from homeassistant.components.adaptive_lighting.switch import (
|
||||
from custom_components.adaptive_lighting.switch import (
|
||||
_SUPPORT_OPTS,
|
||||
VALID_COLOR_MODES,
|
||||
_attributes_have_changed,
|
||||
|
|
@ -48,47 +90,6 @@ from homeassistant.components.adaptive_lighting.switch import (
|
|||
create_context,
|
||||
is_our_context,
|
||||
)
|
||||
from homeassistant.components.demo.light import DemoLight
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_BRIGHTNESS_PCT,
|
||||
ATTR_COLOR_TEMP_KELVIN,
|
||||
ATTR_MAX_COLOR_TEMP_KELVIN,
|
||||
ATTR_MIN_COLOR_TEMP_KELVIN,
|
||||
ATTR_RGB_COLOR,
|
||||
ATTR_SUPPORTED_COLOR_MODES,
|
||||
ATTR_TRANSITION,
|
||||
ATTR_XY_COLOR,
|
||||
COLOR_MODE_BRIGHTNESS,
|
||||
)
|
||||
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
||||
from homeassistant.components.light import SERVICE_TURN_OFF
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
import homeassistant.config as config_util
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import (
|
||||
ATTR_AREA_ID,
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
CONF_LIGHTS,
|
||||
CONF_NAME,
|
||||
CONF_PLATFORM,
|
||||
EVENT_STATE_CHANGED,
|
||||
SERVICE_TURN_ON,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
)
|
||||
from homeassistant.core import Context, State
|
||||
from homeassistant.helpers import entity_registry
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util.color import color_temperature_mired_to_kelvin
|
||||
import homeassistant.util.dt as dt_util
|
||||
import pytest
|
||||
import ulid_transform
|
||||
import voluptuous.error
|
||||
|
||||
from tests.common import MockConfigEntry, mock_area_registry
|
||||
from tests.components.demo.test_light import ENTITY_LIGHT
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -113,6 +114,7 @@ LAT_LONG_TZS = [
|
|||
(32.87336, -117.22743, "US/Pacific"),
|
||||
]
|
||||
|
||||
ENTITY_LIGHT = "light.bed_light"
|
||||
_SWITCH_FMT = f"{SWITCH_DOMAIN}.{DOMAIN}"
|
||||
ENTITY_SWITCH = f"{_SWITCH_FMT}_{DEFAULT_NAME}"
|
||||
ENTITY_SLEEP_MODE_SWITCH = f"{_SWITCH_FMT}_sleep_mode_{DEFAULT_NAME}"
|
||||
|
|
@ -149,50 +151,60 @@ async def setup_switch(hass, extra_data):
|
|||
return entry, switch
|
||||
|
||||
|
||||
async def setup_lights(hass):
|
||||
"""Set up 3 light entities using the 'test' platform."""
|
||||
async def setup_lights(hass: HomeAssistant):
|
||||
"""Set up 3 light entities using the 'template' platform."""
|
||||
await async_setup_component(
|
||||
hass, LIGHT_DOMAIN, {LIGHT_DOMAIN: {"platform": "demo"}}
|
||||
hass,
|
||||
LIGHT_DOMAIN,
|
||||
{
|
||||
LIGHT_DOMAIN: [
|
||||
{
|
||||
"platform": "template",
|
||||
"lights": {
|
||||
"bed_light": {
|
||||
"friendly_name": "Bed Light",
|
||||
"unique_id": "light_1",
|
||||
"turn_on": None,
|
||||
"turn_off": None,
|
||||
"set_level": None,
|
||||
"set_temperature": None,
|
||||
"set_color": None,
|
||||
},
|
||||
"ceiling_lights": {
|
||||
"friendly_name": "Ceiling Lights",
|
||||
"unique_id": "light_2",
|
||||
"turn_on": None,
|
||||
"turn_off": None,
|
||||
"set_level": None,
|
||||
"set_temperature": None,
|
||||
"set_color": None,
|
||||
},
|
||||
"kitchen_lights": {
|
||||
"friendly_name": "Kitchen Lights",
|
||||
"unique_id": "light_3",
|
||||
"turn_on": None,
|
||||
"turn_off": None,
|
||||
"set_level": None,
|
||||
"set_temperature": None,
|
||||
"set_color": None,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
platform = getattr(hass.components, "test.light")
|
||||
while platform.ENTITIES:
|
||||
# Make sure it is empty
|
||||
platform.ENTITIES.pop()
|
||||
lights = [
|
||||
DemoLight(
|
||||
unique_id="light_1",
|
||||
name="Bed Light",
|
||||
state=True,
|
||||
ct=200,
|
||||
),
|
||||
DemoLight(
|
||||
unique_id="light_2",
|
||||
name="Ceiling Lights",
|
||||
state=True,
|
||||
ct=380,
|
||||
),
|
||||
DemoLight(
|
||||
unique_id="light_3",
|
||||
name="Kitchen Lights",
|
||||
state=False,
|
||||
hs_color=(345, 75),
|
||||
ct=240,
|
||||
),
|
||||
]
|
||||
await hass.async_block_till_done()
|
||||
platform = async_get_platforms(hass, "template")
|
||||
lights = list(platform[0].entities.values())
|
||||
|
||||
await lights[0].async_turn_on()
|
||||
await lights[1].async_turn_on()
|
||||
|
||||
for light in lights:
|
||||
light.hass = hass
|
||||
slug = light.name.lower().replace(" ", "_")
|
||||
light.entity_id = f"light.{slug}"
|
||||
await light.async_update_ha_state()
|
||||
light._attr_brightness = 255
|
||||
light._attr_color_temp = 250
|
||||
|
||||
platform.ENTITIES.extend(lights)
|
||||
platform.init()
|
||||
assert await async_setup_component(
|
||||
hass, LIGHT_DOMAIN, {LIGHT_DOMAIN: {CONF_PLATFORM: "test"}}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert all(hass.states.get(light.entity_id) is not None for light in lights)
|
||||
return lights
|
||||
|
||||
|
|
@ -646,11 +658,12 @@ async def test_manual_control(hass):
|
|||
await update()
|
||||
|
||||
def increased_brightness():
|
||||
return (light._brightness + 100) % 255
|
||||
return (light._attr_brightness + 100) % 255
|
||||
|
||||
def increased_color_temp():
|
||||
return max(
|
||||
(light._ct + 100) % light.max_color_temp_kelvin, light.min_color_temp_kelvin
|
||||
(light._attr_color_temp + 100) % light.max_color_temp_kelvin,
|
||||
light.min_color_temp_kelvin,
|
||||
)
|
||||
|
||||
# Nothing is manually controlled
|
||||
|
|
@ -703,7 +716,9 @@ async def test_manual_control(hass):
|
|||
color_temperature_mired_to_kelvin(mired_range[0]),
|
||||
)
|
||||
ptp_kelvin = kelvin_range[1] - kelvin_range[0]
|
||||
await turn_light(True, color_temp_kelvin=(light._ct + 100) % ptp_kelvin)
|
||||
await turn_light(
|
||||
True, color_temp_kelvin=(light._attr_color_temp + 100) % ptp_kelvin
|
||||
)
|
||||
assert manual_control[ENTITY_LIGHT]
|
||||
await switch.adapt_brightness_switch.async_turn_on() # turn on again
|
||||
|
||||
|
|
@ -805,11 +820,12 @@ async def test_apply_service(hass):
|
|||
assert entity_id not in switch._lights
|
||||
|
||||
def increased_brightness():
|
||||
return (light._brightness + 100) % 255
|
||||
return (light._attr_brightness + 100) % 255
|
||||
|
||||
def increased_color_temp():
|
||||
return max(
|
||||
(light._ct + 100) % light.max_color_temp_kelvin, light.min_color_temp_kelvin
|
||||
(light._attr_color_temp + 100) % light.max_color_temp_kelvin,
|
||||
light.min_color_temp_kelvin,
|
||||
)
|
||||
|
||||
async def change_light():
|
||||
|
|
@ -1306,7 +1322,7 @@ async def test_area(hass):
|
|||
area_registry.async_create("test_area")
|
||||
|
||||
entity = entity_registry.async_get(hass).async_get_or_create(
|
||||
LIGHT_DOMAIN, "demo", light.unique_id
|
||||
LIGHT_DOMAIN, "template", light.unique_id
|
||||
)
|
||||
entity = entity_registry.async_get(hass).async_update_entity(
|
||||
entity.entity_id, area_id="test_area"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue