[climate_ir] Only advertise HEAT_COOL when heat and cool are both supported (#19483)

This commit is contained in:
Leonardo Rivera
2026-09-23 11:14:57 +01:00
committed by GitHub
parent e8d3c06b60
commit 00fa63ea19
17 changed files with 262 additions and 5 deletions
@@ -0,0 +1,15 @@
esphome:
name: climateir-heatcool
esp8266:
board: esp01_1m
remote_transmitter:
pin: GPIO5
carrier_duty_percent: 50%
climate:
- platform: coolix
id: test_coolix
name: Coolix
supports_heat: false
@@ -0,0 +1,16 @@
esphome:
name: climateir-heatcool
esp8266:
board: esp01_1m
remote_transmitter:
pin: GPIO5
carrier_duty_percent: 50%
climate:
- platform: coolix
id: test_coolix
name: Coolix
supports_heat: false
supports_heat_cool: true
@@ -0,0 +1,14 @@
esphome:
name: climateir-heatcool
esp8266:
board: esp01_1m
remote_transmitter:
pin: GPIO5
carrier_duty_percent: 50%
climate:
- platform: coolix
id: test_coolix
name: Coolix
@@ -0,0 +1,15 @@
esphome:
name: climateir-heatcool
esp8266:
board: esp01_1m
remote_transmitter:
pin: GPIO5
carrier_duty_percent: 50%
climate:
- platform: coolix
id: test_coolix
name: Coolix
supports_heat_cool: false
@@ -0,0 +1,15 @@
esphome:
name: climateir-heatcool
esp8266:
board: esp01_1m
remote_transmitter:
pin: GPIO5
carrier_duty_percent: 50%
climate:
- platform: coolix
id: test_coolix
name: Coolix
supports_cool: false
@@ -0,0 +1,16 @@
esphome:
name: climateir-heatcool
esp8266:
board: esp01_1m
remote_transmitter:
pin: GPIO5
carrier_duty_percent: 50%
climate:
- platform: coolix
id: test_coolix
name: Coolix
supports_heat: false
supports_cool: false
@@ -0,0 +1,53 @@
"""Tests for the supports_heat_cool default resolved in climate_ir code generation."""
from __future__ import annotations
from collections.abc import Callable
from pathlib import Path
import re
import pytest
def _emitted_value(main_cpp: str) -> str | None:
"""Return the argument of the generated set_supports_heat_cool() call, or None if absent."""
match = re.search(r"set_supports_heat_cool\((true|false)\)", main_cpp)
return match.group(1) if match else None
@pytest.mark.parametrize(
("config", "expected"),
[
("heat_and_cool.yaml", None),
("cool_only.yaml", "false"),
("heat_only.yaml", "false"),
("neither.yaml", "false"),
],
)
def test_default_requires_heat_and_cool(
config: str,
expected: str | None,
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
"""Without the key, HEAT_COOL follows supports_heat and supports_cool."""
main_cpp = generate_main(component_config_path(config))
assert _emitted_value(main_cpp) == expected
@pytest.mark.parametrize(
("config", "expected"),
[
("cool_only_override_on.yaml", None),
("heat_and_cool_override_off.yaml", "false"),
],
)
def test_explicit_key_overrides_default(
config: str,
expected: str | None,
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
"""A cool-only unit can still offer HEAT_COOL, and a heat+cool unit can drop it."""
main_cpp = generate_main(component_config_path(config))
assert _emitted_value(main_cpp) == expected