|
3 | 3 | import asyncio
|
4 | 4 | from copy import deepcopy
|
5 | 5 | import datetime
|
| 6 | +import itertools |
6 | 7 | import logging
|
7 | 8 | from random import randint
|
8 |
| -from unittest.mock import patch |
| 9 | +from unittest.mock import MagicMock, patch |
9 | 10 |
|
10 | 11 | from homeassistant.components.adaptive_lighting.const import (
|
11 | 12 | ADAPT_BRIGHTNESS_SWITCH,
|
|
25 | 26 | CONF_TRANSITION,
|
26 | 27 | CONF_TURN_ON_LIGHTS,
|
27 | 28 | CONF_USE_DEFAULTS,
|
| 29 | + CONST_COLOR, |
28 | 30 | DEFAULT_MAX_BRIGHTNESS,
|
29 | 31 | DEFAULT_NAME,
|
30 | 32 | DEFAULT_SLEEP_BRIGHTNESS,
|
|
37 | 39 | UNDO_UPDATE_LISTENER,
|
38 | 40 | )
|
39 | 41 | from homeassistant.components.adaptive_lighting.switch import (
|
| 42 | + _SUPPORT_OPTS, |
| 43 | + VALID_COLOR_MODES, |
40 | 44 | _attributes_have_changed,
|
| 45 | + _supported_features, |
41 | 46 | color_difference_redmean,
|
42 | 47 | create_context,
|
43 | 48 | is_our_context,
|
|
47 | 52 | ATTR_BRIGHTNESS,
|
48 | 53 | ATTR_BRIGHTNESS_PCT,
|
49 | 54 | ATTR_COLOR_TEMP_KELVIN,
|
| 55 | + ATTR_MAX_COLOR_TEMP_KELVIN, |
| 56 | + ATTR_MIN_COLOR_TEMP_KELVIN, |
50 | 57 | ATTR_RGB_COLOR,
|
| 58 | + ATTR_SUPPORTED_COLOR_MODES, |
51 | 59 | ATTR_TRANSITION,
|
52 | 60 | ATTR_XY_COLOR,
|
| 61 | + COLOR_MODE_BRIGHTNESS, |
53 | 62 | )
|
54 | 63 | from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
55 | 64 | from homeassistant.components.light import SERVICE_TURN_OFF
|
@@ -515,6 +524,79 @@ async def test_turn_on_off_listener_not_tracking_untracked_lights(hass):
|
515 | 524 | assert light not in switch.turn_on_off_listener.lights
|
516 | 525 |
|
517 | 526 |
|
| 527 | +def test_supported_features(hass): # noqa: C901 |
| 528 | + """Test the supported features of a light.""" |
| 529 | + |
| 530 | + possible_legacy_features = {} |
| 531 | + MAX_COMBINATIONS = 4 # maximum number of elements that can be combined |
| 532 | + for i in range(1, min(MAX_COMBINATIONS, len(_SUPPORT_OPTS)) + 1): |
| 533 | + for combination in itertools.combinations(_SUPPORT_OPTS.keys(), i): |
| 534 | + key = "_".join(combination) |
| 535 | + value = [v for k, v in _SUPPORT_OPTS.items() if k in combination] |
| 536 | + possible_legacy_features[key] = value |
| 537 | + |
| 538 | + possible_color_modes = {} |
| 539 | + for i in range(1, len(VALID_COLOR_MODES) + 1): |
| 540 | + for combination in itertools.combinations(VALID_COLOR_MODES.keys(), i): |
| 541 | + key = "_".join(combination) |
| 542 | + value = [v for k, v in VALID_COLOR_MODES.items() if k in combination] |
| 543 | + possible_color_modes[key] = value |
| 544 | + |
| 545 | + # create a mock HomeAssistant object |
| 546 | + hass = MagicMock() |
| 547 | + |
| 548 | + # iterate over possible legacy features |
| 549 | + for feature_key, feature_values in possible_legacy_features.items(): |
| 550 | + # _LOGGER.debug(feature_values) |
| 551 | + # set the attributes of the mock state object to the possible legacy feature values |
| 552 | + state_attrs = {ATTR_SUPPORTED_FEATURES: sum(feature_values)} |
| 553 | + hass.states.get.return_value.attributes = state_attrs |
| 554 | + |
| 555 | + # iterate over possible color modes |
| 556 | + for mode_key, mode_values in possible_color_modes.items(): |
| 557 | + # _LOGGER.debug(mode_values) |
| 558 | + # set the attributes of the mock state object to the possible color mode values |
| 559 | + state_attrs[ATTR_SUPPORTED_COLOR_MODES] = set(mode_values) |
| 560 | + hass.states.get.return_value.attributes = state_attrs |
| 561 | + |
| 562 | + # Handle both the new and the old _supported_features. |
| 563 | + result = _supported_features(hass, ENTITY_LIGHT) |
| 564 | + supported, supports_colors = ( |
| 565 | + result if isinstance(result, tuple) else (result, None) |
| 566 | + ) |
| 567 | + expected_supported = {} if supports_colors is not None else set() |
| 568 | + for mode, attr in VALID_COLOR_MODES.items(): |
| 569 | + if mode in mode_values: |
| 570 | + if supports_colors is None: |
| 571 | + expected_supported.add(mode) |
| 572 | + else: |
| 573 | + expected_supported[attr] = True |
| 574 | + if supports_colors is True: |
| 575 | + expected_supported[COLOR_MODE_BRIGHTNESS] = True |
| 576 | + for opt, value in _SUPPORT_OPTS.items(): |
| 577 | + if value in feature_values: |
| 578 | + if supports_colors is None: |
| 579 | + expected_supported.add(opt) |
| 580 | + else: |
| 581 | + if supports_colors is True: |
| 582 | + expected_supported[COLOR_MODE_BRIGHTNESS] = True |
| 583 | + if opt in VALID_COLOR_MODES: |
| 584 | + expected_supported[VALID_COLOR_MODES[opt]] = True |
| 585 | + elif opt != CONST_COLOR: |
| 586 | + expected_supported[opt] = True |
| 587 | + if ATTR_MIN_COLOR_TEMP_KELVIN in supported: |
| 588 | + supported.pop(ATTR_MIN_COLOR_TEMP_KELVIN) |
| 589 | + if ATTR_MAX_COLOR_TEMP_KELVIN in supported: |
| 590 | + supported.pop(ATTR_MAX_COLOR_TEMP_KELVIN) |
| 591 | + assert supported == expected_supported, ( |
| 592 | + f"\nExpected supported: {expected_supported}\n" |
| 593 | + f"Actual supported: {supported}\n" |
| 594 | + f"feature_values: {feature_values}\n" |
| 595 | + f"mode_values: {mode_values}\n" |
| 596 | + f"supports_colors: {supports_colors}\n" |
| 597 | + ) |
| 598 | + |
| 599 | + |
518 | 600 | @pytest.mark.dependency(depends=GLOBAL_TEST_DEPENDENCIES)
|
519 | 601 | async def test_manual_control(hass):
|
520 | 602 | """Test the 'manual control' tracking."""
|
|
0 commit comments