Improve tests for template binary sensor (#62103)

This commit is contained in:
Erik Montnemery 2021-12-16 21:31:37 +01:00 committed by GitHub
parent 4de4cc7bd4
commit 4353b1e62c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -6,7 +6,7 @@ from unittest.mock import patch
import pytest import pytest
from homeassistant import setup from homeassistant import setup
from homeassistant.components import binary_sensor from homeassistant.components import binary_sensor, template
from homeassistant.const import ( from homeassistant.const import (
ATTR_DEVICE_CLASS, ATTR_DEVICE_CLASS,
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_START,
@ -24,56 +24,150 @@ ON = "on"
OFF = "off" OFF = "off"
@pytest.mark.parametrize("count,domain", [(1, binary_sensor.DOMAIN)]) @pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"config", "config,domain,entity_id,name,attributes",
[ [
{ (
"binary_sensor": { {
"platform": "template", "binary_sensor": {
"sensors": { "platform": "template",
"test": { "sensors": {
"friendly_name": "virtual thingy", "test": {
"value_template": "{{ True }}", "value_template": "{{ True }}",
}
},
},
},
binary_sensor.DOMAIN,
"binary_sensor.test",
"test",
{"friendly_name": "test"},
),
(
{
"template": {
"binary_sensor": {
"state": "{{ True }}",
}
},
},
template.DOMAIN,
"binary_sensor.unnamed_device",
"unnamed device",
{},
),
],
)
async def test_setup_minimal(hass, start_ha, entity_id, name, attributes):
"""Test the setup."""
state = hass.states.get(entity_id)
assert state is not None
assert state.name == name
assert state.state == ON
assert state.attributes == attributes
@pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize(
"config,domain,entity_id",
[
(
{
"binary_sensor": {
"platform": "template",
"sensors": {
"test": {
"friendly_name": "virtual thingy",
"value_template": "{{ True }}",
"device_class": "motion",
}
},
},
},
binary_sensor.DOMAIN,
"binary_sensor.test",
),
(
{
"template": {
"binary_sensor": {
"name": "virtual thingy",
"state": "{{ True }}",
"device_class": "motion", "device_class": "motion",
} }
}, },
}, },
}, template.DOMAIN,
"binary_sensor.virtual_thingy",
),
], ],
) )
async def test_setup_legacy(hass, start_ha): async def test_setup(hass, start_ha, entity_id):
"""Test the setup.""" """Test the setup."""
state = hass.states.get("binary_sensor.test") state = hass.states.get(entity_id)
assert state is not None assert state is not None
assert state.name == "virtual thingy" assert state.name == "virtual thingy"
assert state.state == ON assert state.state == ON
assert state.attributes["device_class"] == "motion" assert state.attributes["device_class"] == "motion"
@pytest.mark.parametrize("count,domain", [(0, binary_sensor.DOMAIN)]) @pytest.mark.parametrize("count", [0])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"config", "config,domain",
[ [
{"binary_sensor": {"platform": "template"}}, # No legacy binary sensors
{"binary_sensor": {"platform": "template", "sensors": {"foo bar": {}}}}, (
{ {"binary_sensor": {"platform": "template"}},
"binary_sensor": { binary_sensor.DOMAIN,
"platform": "template", ),
"sensors": { # Legacy binary sensor missing mandatory config
"test": { (
"value_template": "{{ foo }}", {"binary_sensor": {"platform": "template", "sensors": {"foo bar": {}}}},
binary_sensor.DOMAIN,
),
# Binary sensor missing mandatory config
(
{"template": {"binary_sensor": {}}},
template.DOMAIN,
),
# Legacy binary sensor with invalid device class
(
{
"binary_sensor": {
"platform": "template",
"sensors": {
"test": {
"value_template": "{{ foo }}",
"device_class": "foobarnotreal",
}
},
}
},
binary_sensor.DOMAIN,
),
# Binary sensor with invalid device class
(
{
"template": {
"binary_sensor": {
"state": "{{ foo }}",
"device_class": "foobarnotreal", "device_class": "foobarnotreal",
} }
}, }
} },
}, template.DOMAIN,
{ ),
"binary_sensor": { # Legacy binary sensor missing mandatory config
"platform": "template", (
"sensors": {"test": {"device_class": "motion"}}, {
} "binary_sensor": {
}, "platform": "template",
"sensors": {"test": {"device_class": "motion"}},
}
},
binary_sensor.DOMAIN,
),
], ],
) )
async def test_setup_invalid_sensors(hass, count, start_ha): async def test_setup_invalid_sensors(hass, count, start_ha):
@ -81,17 +175,35 @@ async def test_setup_invalid_sensors(hass, count, start_ha):
assert len(hass.states.async_entity_ids("binary_sensor")) == count assert len(hass.states.async_entity_ids("binary_sensor")) == count
@pytest.mark.parametrize("count,domain", [(1, binary_sensor.DOMAIN)]) @pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"config", "config,domain,entity_id",
[ [
{ (
"binary_sensor": { {
"platform": "template", "binary_sensor": {
"sensors": { "platform": "template",
"test_template_sensor": { "sensors": {
"value_template": "{{ states.sensor.xyz.state }}", "test_template_sensor": {
"icon_template": "{% if " "value_template": "{{ states.sensor.xyz.state }}",
"icon_template": "{% if "
"states.binary_sensor.test_state.state == "
"'Works' %}"
"mdi:check"
"{% endif %}",
},
},
},
},
binary_sensor.DOMAIN,
"binary_sensor.test_template_sensor",
),
(
{
"template": {
"binary_sensor": {
"state": "{{ states.sensor.xyz.state }}",
"icon": "{% if "
"states.binary_sensor.test_state.state == " "states.binary_sensor.test_state.state == "
"'Works' %}" "'Works' %}"
"mdi:check" "mdi:check"
@ -99,31 +211,51 @@ async def test_setup_invalid_sensors(hass, count, start_ha):
}, },
}, },
}, },
}, template.DOMAIN,
"binary_sensor.unnamed_device",
),
], ],
) )
async def test_icon_template(hass, start_ha): async def test_icon_template(hass, start_ha, entity_id):
"""Test icon template.""" """Test icon template."""
state = hass.states.get("binary_sensor.test_template_sensor") state = hass.states.get(entity_id)
assert state.attributes.get("icon") == "" assert state.attributes.get("icon") == ""
hass.states.async_set("binary_sensor.test_state", "Works") hass.states.async_set("binary_sensor.test_state", "Works")
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get("binary_sensor.test_template_sensor") state = hass.states.get(entity_id)
assert state.attributes["icon"] == "mdi:check" assert state.attributes["icon"] == "mdi:check"
@pytest.mark.parametrize("count,domain", [(1, binary_sensor.DOMAIN)]) @pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"config", "config,domain,entity_id",
[ [
{ (
"binary_sensor": { {
"platform": "template", "binary_sensor": {
"sensors": { "platform": "template",
"test_template_sensor": { "sensors": {
"value_template": "{{ states.sensor.xyz.state }}", "test_template_sensor": {
"entity_picture_template": "{% if " "value_template": "{{ states.sensor.xyz.state }}",
"entity_picture_template": "{% if "
"states.binary_sensor.test_state.state == "
"'Works' %}"
"/local/sensor.png"
"{% endif %}",
},
},
},
},
binary_sensor.DOMAIN,
"binary_sensor.test_template_sensor",
),
(
{
"template": {
"binary_sensor": {
"state": "{{ states.sensor.xyz.state }}",
"picture": "{% if "
"states.binary_sensor.test_state.state == " "states.binary_sensor.test_state.state == "
"'Works' %}" "'Works' %}"
"/local/sensor.png" "/local/sensor.png"
@ -131,48 +263,68 @@ async def test_icon_template(hass, start_ha):
}, },
}, },
}, },
}, template.DOMAIN,
"binary_sensor.unnamed_device",
),
], ],
) )
async def test_entity_picture_template(hass, start_ha): async def test_entity_picture_template(hass, start_ha, entity_id):
"""Test entity_picture template.""" """Test entity_picture template."""
state = hass.states.get("binary_sensor.test_template_sensor") state = hass.states.get(entity_id)
assert state.attributes.get("entity_picture") == "" assert state.attributes.get("entity_picture") == ""
hass.states.async_set("binary_sensor.test_state", "Works") hass.states.async_set("binary_sensor.test_state", "Works")
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get("binary_sensor.test_template_sensor") state = hass.states.get(entity_id)
assert state.attributes["entity_picture"] == "/local/sensor.png" assert state.attributes["entity_picture"] == "/local/sensor.png"
@pytest.mark.parametrize("count,domain", [(1, binary_sensor.DOMAIN)]) @pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"config", "config,domain,entity_id",
[ [
{ (
"binary_sensor": { {
"platform": "template", "binary_sensor": {
"sensors": { "platform": "template",
"test_template_sensor": { "sensors": {
"value_template": "{{ states.sensor.xyz.state }}", "test_template_sensor": {
"attribute_templates": { "value_template": "{{ states.sensor.xyz.state }}",
"attribute_templates": {
"test_attribute": "It {{ states.sensor.test_state.state }}."
},
},
},
},
},
binary_sensor.DOMAIN,
"binary_sensor.test_template_sensor",
),
(
{
"template": {
"binary_sensor": {
"state": "{{ states.sensor.xyz.state }}",
"attributes": {
"test_attribute": "It {{ states.sensor.test_state.state }}." "test_attribute": "It {{ states.sensor.test_state.state }}."
}, },
}, },
}, },
}, },
}, template.DOMAIN,
"binary_sensor.unnamed_device",
),
], ],
) )
async def test_attribute_templates(hass, start_ha): async def test_attribute_templates(hass, start_ha, entity_id):
"""Test attribute_templates template.""" """Test attribute_templates template."""
state = hass.states.get("binary_sensor.test_template_sensor") state = hass.states.get(entity_id)
assert state.attributes.get("test_attribute") == "It ." assert state.attributes.get("test_attribute") == "It ."
hass.states.async_set("sensor.test_state", "Works2") hass.states.async_set("sensor.test_state", "Works2")
await hass.async_block_till_done() await hass.async_block_till_done()
hass.states.async_set("sensor.test_state", "Works") hass.states.async_set("sensor.test_state", "Works")
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get("binary_sensor.test_template_sensor") state = hass.states.get(entity_id)
assert state.attributes["test_attribute"] == "It Works." assert state.attributes["test_attribute"] == "It Works."
@ -247,67 +399,102 @@ async def test_event(hass, start_ha):
assert state.state == ON assert state.state == ON
@pytest.mark.parametrize("count,domain", [(1, binary_sensor.DOMAIN)])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"config", "config,count,domain",
[ [
{ (
"binary_sensor": { {
"platform": "template", "binary_sensor": {
"sensors": { "platform": "template",
"test_on": { "sensors": {
"friendly_name": "virtual thingy", "test_on": {
"value_template": "{{ states.sensor.test_state.state == 'on' }}", "friendly_name": "virtual thingy",
"device_class": "motion", "value_template": "{{ states.sensor.test_state.state == 'on' }}",
"delay_on": 5, "device_class": "motion",
}, "delay_on": 5,
"test_off": { },
"friendly_name": "virtual thingy", "test_off": {
"value_template": "{{ states.sensor.test_state.state == 'on' }}", "friendly_name": "virtual thingy",
"device_class": "motion", "value_template": "{{ states.sensor.test_state.state == 'on' }}",
"delay_off": 5, "device_class": "motion",
"delay_off": 5,
},
}, },
}, },
}, },
}, 1,
{ binary_sensor.DOMAIN,
"binary_sensor": { ),
"platform": "template", (
"sensors": { {
"test_on": { "template": [
"friendly_name": "virtual thingy", {
"value_template": "{{ states.sensor.test_state.state == 'on' }}", "binary_sensor": {
"device_class": "motion", "name": "test on",
"delay_on": '{{ ({ "seconds": 10 / 2 }) }}', "state": "{{ states.sensor.test_state.state == 'on' }}",
"device_class": "motion",
"delay_on": 5,
},
}, },
"test_off": { {
"friendly_name": "virtual thingy", "binary_sensor": {
"value_template": "{{ states.sensor.test_state.state == 'on' }}", "name": "test off",
"device_class": "motion", "state": "{{ states.sensor.test_state.state == 'on' }}",
"delay_off": '{{ ({ "seconds": 10 / 2 }) }}', "device_class": "motion",
"delay_off": 5,
},
},
]
},
2,
template.DOMAIN,
),
(
{
"binary_sensor": {
"platform": "template",
"sensors": {
"test_on": {
"friendly_name": "virtual thingy",
"value_template": "{{ states.sensor.test_state.state == 'on' }}",
"device_class": "motion",
"delay_on": '{{ ({ "seconds": 10 / 2 }) }}',
},
"test_off": {
"friendly_name": "virtual thingy",
"value_template": "{{ states.sensor.test_state.state == 'on' }}",
"device_class": "motion",
"delay_off": '{{ ({ "seconds": 10 / 2 }) }}',
},
}, },
}, },
}, },
}, 1,
{ binary_sensor.DOMAIN,
"binary_sensor": { ),
"platform": "template", (
"sensors": { {
"test_on": { "binary_sensor": {
"friendly_name": "virtual thingy", "platform": "template",
"value_template": "{{ states.sensor.test_state.state == 'on' }}", "sensors": {
"device_class": "motion", "test_on": {
"delay_on": '{{ ({ "seconds": states("input_number.delay")|int }) }}', "friendly_name": "virtual thingy",
}, "value_template": "{{ states.sensor.test_state.state == 'on' }}",
"test_off": { "device_class": "motion",
"friendly_name": "virtual thingy", "delay_on": '{{ ({ "seconds": states("input_number.delay")|int }) }}',
"value_template": "{{ states.sensor.test_state.state == 'on' }}", },
"device_class": "motion", "test_off": {
"delay_off": '{{ ({ "seconds": states("input_number.delay")|int }) }}', "friendly_name": "virtual thingy",
"value_template": "{{ states.sensor.test_state.state == 'on' }}",
"device_class": "motion",
"delay_off": '{{ ({ "seconds": states("input_number.delay")|int }) }}',
},
}, },
}, },
}, },
}, 1,
binary_sensor.DOMAIN,
),
], ],
) )
async def test_template_delay_on_off(hass, start_ha): async def test_template_delay_on_off(hass, start_ha):
@ -349,64 +536,101 @@ async def test_template_delay_on_off(hass, start_ha):
assert hass.states.get("binary_sensor.test_off").state == OFF assert hass.states.get("binary_sensor.test_off").state == OFF
@pytest.mark.parametrize("count,domain", [(1, binary_sensor.DOMAIN)]) @pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"config", "config,domain,entity_id",
[ [
{ (
"binary_sensor": { {
"platform": "template", "binary_sensor": {
"sensors": { "platform": "template",
"test": { "sensors": {
"friendly_name": "virtual thingy", "test": {
"value_template": "true", "friendly_name": "virtual thingy",
"value_template": "true",
"device_class": "motion",
"delay_off": 5,
},
},
},
},
binary_sensor.DOMAIN,
"binary_sensor.test",
),
(
{
"template": {
"binary_sensor": {
"name": "virtual thingy",
"state": "true",
"device_class": "motion", "device_class": "motion",
"delay_off": 5, "delay_off": 5,
}, },
}, },
}, },
}, template.DOMAIN,
"binary_sensor.virtual_thingy",
),
], ],
) )
async def test_available_without_availability_template(hass, start_ha): async def test_available_without_availability_template(hass, start_ha, entity_id):
"""Ensure availability is true without an availability_template.""" """Ensure availability is true without an availability_template."""
state = hass.states.get("binary_sensor.test") state = hass.states.get(entity_id)
assert state.state != STATE_UNAVAILABLE assert state.state != STATE_UNAVAILABLE
assert state.attributes[ATTR_DEVICE_CLASS] == "motion" assert state.attributes[ATTR_DEVICE_CLASS] == "motion"
@pytest.mark.parametrize("count,domain", [(1, binary_sensor.DOMAIN)]) @pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"config", "config,domain,entity_id",
[ [
{ (
"binary_sensor": { {
"platform": "template", "binary_sensor": {
"sensors": { "platform": "template",
"test": { "sensors": {
"friendly_name": "virtual thingy", "test": {
"value_template": "true", "friendly_name": "virtual thingy",
"device_class": "motion", "value_template": "true",
"delay_off": 5, "device_class": "motion",
"availability_template": "{{ is_state('sensor.test_state','on') }}", "delay_off": 5,
"availability_template": "{{ is_state('sensor.test_state','on') }}",
},
}, },
}, },
}, },
}, binary_sensor.DOMAIN,
"binary_sensor.test",
),
(
{
"template": {
"binary_sensor": {
"name": "virtual thingy",
"state": "true",
"device_class": "motion",
"delay_off": 5,
"availability": "{{ is_state('sensor.test_state','on') }}",
},
},
},
template.DOMAIN,
"binary_sensor.virtual_thingy",
),
], ],
) )
async def test_availability_template(hass, start_ha): async def test_availability_template(hass, start_ha, entity_id):
"""Test availability template.""" """Test availability template."""
hass.states.async_set("sensor.test_state", STATE_OFF) hass.states.async_set("sensor.test_state", STATE_OFF)
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get("binary_sensor.test").state == STATE_UNAVAILABLE assert hass.states.get(entity_id).state == STATE_UNAVAILABLE
hass.states.async_set("sensor.test_state", STATE_ON) hass.states.async_set("sensor.test_state", STATE_ON)
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get("binary_sensor.test") state = hass.states.get(entity_id)
assert state.state != STATE_UNAVAILABLE assert state.state != STATE_UNAVAILABLE
assert state.attributes[ATTR_DEVICE_CLASS] == "motion" assert state.attributes[ATTR_DEVICE_CLASS] == "motion"