Allow input_number entity_id as for numeric_state trigger thresholds (#45091)

* Allow input_number as limits for numeric_state trigger

* Rename threshold schema
This commit is contained in:
Alexei Chetroi 2021-01-13 10:20:59 -05:00 committed by GitHub
parent 83b210061d
commit de8f273bd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 344 additions and 111 deletions

View File

@ -32,6 +32,9 @@ def validate_above_below(value):
if above is None or below is None:
return value
if isinstance(above, str) or isinstance(below, str):
return value
if above > below:
raise vol.Invalid(
f"A value can never be above {above} and below {below} at the same time. You probably want two different triggers.",
@ -45,8 +48,8 @@ TRIGGER_SCHEMA = vol.All(
{
vol.Required(CONF_PLATFORM): "numeric_state",
vol.Required(CONF_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_BELOW): vol.Coerce(float),
vol.Optional(CONF_ABOVE): vol.Coerce(float),
vol.Optional(CONF_BELOW): cv.NUMERIC_STATE_THRESHOLD_SCHEMA,
vol.Optional(CONF_ABOVE): cv.NUMERIC_STATE_THRESHOLD_SCHEMA,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_FOR): cv.positive_time_period_template,
vol.Optional(CONF_ATTRIBUTE): cv.match_all,

View File

@ -916,18 +916,18 @@ SERVICE_SCHEMA = vol.All(
has_at_least_one_key(CONF_SERVICE, CONF_SERVICE_TEMPLATE),
)
NUMERIC_STATE_THRESHOLD_SCHEMA = vol.Any(
vol.Coerce(float), vol.All(str, entity_domain("input_number"))
)
NUMERIC_STATE_CONDITION_SCHEMA = vol.All(
vol.Schema(
{
vol.Required(CONF_CONDITION): "numeric_state",
vol.Required(CONF_ENTITY_ID): entity_ids,
vol.Optional(CONF_ATTRIBUTE): str,
CONF_BELOW: vol.Any(
vol.Coerce(float), vol.All(str, entity_domain("input_number"))
),
CONF_ABOVE: vol.Any(
vol.Coerce(float), vol.All(str, entity_domain("input_number"))
),
CONF_BELOW: NUMERIC_STATE_THRESHOLD_SCHEMA,
CONF_ABOVE: NUMERIC_STATE_THRESHOLD_SCHEMA,
vol.Optional(CONF_VALUE_TEMPLATE): template,
}
),

View File

@ -29,12 +29,27 @@ def calls(hass):
@pytest.fixture(autouse=True)
def setup_comp(hass):
async def setup_comp(hass):
"""Initialize components."""
mock_component(hass, "group")
await async_setup_component(
hass,
"input_number",
{
"input_number": {
"value_3": {"min": 0, "max": 255, "initial": 3},
"value_5": {"min": 0, "max": 255, "initial": 5},
"value_8": {"min": 0, "max": 255, "initial": 8},
"value_10": {"min": 0, "max": 255, "initial": 10},
"value_12": {"min": 0, "max": 255, "initial": 12},
"value_100": {"min": 0, "max": 255, "initial": 100},
}
},
)
async def test_if_not_fires_on_entity_removal(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_not_fires_on_entity_removal(hass, calls, below):
"""Test the firing with removed entity."""
hass.states.async_set("test.entity", 11)
@ -46,7 +61,7 @@ async def test_if_not_fires_on_entity_removal(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -59,7 +74,8 @@ async def test_if_not_fires_on_entity_removal(hass, calls):
assert len(calls) == 0
async def test_if_fires_on_entity_change_below(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_fires_on_entity_change_below(hass, calls, below):
"""Test the firing with changed entity."""
hass.states.async_set("test.entity", 11)
await hass.async_block_till_done()
@ -73,7 +89,7 @@ async def test_if_fires_on_entity_change_below(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -99,7 +115,8 @@ async def test_if_fires_on_entity_change_below(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_entity_change_over_to_below(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_fires_on_entity_change_over_to_below(hass, calls, below):
"""Test the firing with changed entity."""
hass.states.async_set("test.entity", 11)
await hass.async_block_till_done()
@ -112,7 +129,7 @@ async def test_if_fires_on_entity_change_over_to_below(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -125,7 +142,8 @@ async def test_if_fires_on_entity_change_over_to_below(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_entities_change_over_to_below(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_fires_on_entities_change_over_to_below(hass, calls, below):
"""Test the firing with changed entities."""
hass.states.async_set("test.entity_1", 11)
hass.states.async_set("test.entity_2", 11)
@ -139,7 +157,7 @@ async def test_if_fires_on_entities_change_over_to_below(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": ["test.entity_1", "test.entity_2"],
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -155,7 +173,8 @@ async def test_if_fires_on_entities_change_over_to_below(hass, calls):
assert len(calls) == 2
async def test_if_not_fires_on_entity_change_below_to_below(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_not_fires_on_entity_change_below_to_below(hass, calls, below):
"""Test the firing with changed entity."""
context = Context()
hass.states.async_set("test.entity", 11)
@ -169,7 +188,7 @@ async def test_if_not_fires_on_entity_change_below_to_below(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -193,7 +212,8 @@ async def test_if_not_fires_on_entity_change_below_to_below(hass, calls):
assert len(calls) == 1
async def test_if_not_below_fires_on_entity_change_to_equal(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_not_below_fires_on_entity_change_to_equal(hass, calls, below):
"""Test the firing with changed entity."""
hass.states.async_set("test.entity", 11)
await hass.async_block_till_done()
@ -206,7 +226,7 @@ async def test_if_not_below_fires_on_entity_change_to_equal(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -219,7 +239,8 @@ async def test_if_not_below_fires_on_entity_change_to_equal(hass, calls):
assert len(calls) == 0
async def test_if_fires_on_initial_entity_below(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_fires_on_initial_entity_below(hass, calls, below):
"""Test the firing when starting with a match."""
hass.states.async_set("test.entity", 9)
await hass.async_block_till_done()
@ -232,7 +253,7 @@ async def test_if_fires_on_initial_entity_below(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -245,7 +266,8 @@ async def test_if_fires_on_initial_entity_below(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_initial_entity_above(hass, calls):
@pytest.mark.parametrize("above", (10, "input_number.value_10"))
async def test_if_fires_on_initial_entity_above(hass, calls, above):
"""Test the firing when starting with a match."""
hass.states.async_set("test.entity", 11)
await hass.async_block_till_done()
@ -258,7 +280,7 @@ async def test_if_fires_on_initial_entity_above(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 10,
"above": above,
},
"action": {"service": "test.automation"},
}
@ -271,7 +293,8 @@ async def test_if_fires_on_initial_entity_above(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_entity_change_above(hass, calls):
@pytest.mark.parametrize("above", (10, "input_number.value_10"))
async def test_if_fires_on_entity_change_above(hass, calls, above):
"""Test the firing with changed entity."""
hass.states.async_set("test.entity", 9)
await hass.async_block_till_done()
@ -284,7 +307,7 @@ async def test_if_fires_on_entity_change_above(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 10,
"above": above,
},
"action": {"service": "test.automation"},
}
@ -296,7 +319,8 @@ async def test_if_fires_on_entity_change_above(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_entity_change_below_to_above(hass, calls):
@pytest.mark.parametrize("above", (10, "input_number.value_10"))
async def test_if_fires_on_entity_change_below_to_above(hass, calls, above):
"""Test the firing with changed entity."""
# set initial state
hass.states.async_set("test.entity", 9)
@ -310,7 +334,7 @@ async def test_if_fires_on_entity_change_below_to_above(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 10,
"above": above,
},
"action": {"service": "test.automation"},
}
@ -323,7 +347,8 @@ async def test_if_fires_on_entity_change_below_to_above(hass, calls):
assert len(calls) == 1
async def test_if_not_fires_on_entity_change_above_to_above(hass, calls):
@pytest.mark.parametrize("above", (10, "input_number.value_10"))
async def test_if_not_fires_on_entity_change_above_to_above(hass, calls, above):
"""Test the firing with changed entity."""
# set initial state
hass.states.async_set("test.entity", 9)
@ -337,7 +362,7 @@ async def test_if_not_fires_on_entity_change_above_to_above(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 10,
"above": above,
},
"action": {"service": "test.automation"},
}
@ -355,7 +380,8 @@ async def test_if_not_fires_on_entity_change_above_to_above(hass, calls):
assert len(calls) == 1
async def test_if_not_above_fires_on_entity_change_to_equal(hass, calls):
@pytest.mark.parametrize("above", (10, "input_number.value_10"))
async def test_if_not_above_fires_on_entity_change_to_equal(hass, calls, above):
"""Test the firing with changed entity."""
# set initial state
hass.states.async_set("test.entity", 9)
@ -369,7 +395,7 @@ async def test_if_not_above_fires_on_entity_change_to_equal(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 10,
"above": above,
},
"action": {"service": "test.automation"},
}
@ -382,7 +408,16 @@ async def test_if_not_above_fires_on_entity_change_to_equal(hass, calls):
assert len(calls) == 0
async def test_if_fires_on_entity_change_below_range(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(5, 10),
(5, "input_number.value_10"),
("input_number.value_5", 10),
("input_number.value_5", "input_number.value_10"),
),
)
async def test_if_fires_on_entity_change_below_range(hass, calls, above, below):
"""Test the firing with changed entity."""
hass.states.async_set("test.entity", 11)
await hass.async_block_till_done()
@ -395,8 +430,8 @@ async def test_if_fires_on_entity_change_below_range(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"above": 5,
"below": below,
"above": above,
},
"action": {"service": "test.automation"},
}
@ -408,7 +443,16 @@ async def test_if_fires_on_entity_change_below_range(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_entity_change_below_above_range(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(5, 10),
(5, "input_number.value_10"),
("input_number.value_5", 10),
("input_number.value_5", "input_number.value_10"),
),
)
async def test_if_fires_on_entity_change_below_above_range(hass, calls, above, below):
"""Test the firing with changed entity."""
assert await async_setup_component(
hass,
@ -418,8 +462,8 @@ async def test_if_fires_on_entity_change_below_above_range(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"above": 5,
"below": below,
"above": above,
},
"action": {"service": "test.automation"},
}
@ -431,7 +475,16 @@ async def test_if_fires_on_entity_change_below_above_range(hass, calls):
assert len(calls) == 0
async def test_if_fires_on_entity_change_over_to_below_range(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(5, 10),
(5, "input_number.value_10"),
("input_number.value_5", 10),
("input_number.value_5", "input_number.value_10"),
),
)
async def test_if_fires_on_entity_change_over_to_below_range(hass, calls, above, below):
"""Test the firing with changed entity."""
hass.states.async_set("test.entity", 11)
await hass.async_block_till_done()
@ -444,8 +497,8 @@ async def test_if_fires_on_entity_change_over_to_below_range(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"above": 5,
"below": below,
"above": above,
},
"action": {"service": "test.automation"},
}
@ -458,7 +511,18 @@ async def test_if_fires_on_entity_change_over_to_below_range(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_entity_change_over_to_below_above_range(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(5, 10),
(5, "input_number.value_10"),
("input_number.value_5", 10),
("input_number.value_5", "input_number.value_10"),
),
)
async def test_if_fires_on_entity_change_over_to_below_above_range(
hass, calls, above, below
):
"""Test the firing with changed entity."""
hass.states.async_set("test.entity", 11)
await hass.async_block_till_done()
@ -471,8 +535,8 @@ async def test_if_fires_on_entity_change_over_to_below_above_range(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"above": 5,
"below": above,
"above": below,
},
"action": {"service": "test.automation"},
}
@ -485,7 +549,8 @@ async def test_if_fires_on_entity_change_over_to_below_above_range(hass, calls):
assert len(calls) == 0
async def test_if_not_fires_if_entity_not_match(hass, calls):
@pytest.mark.parametrize("below", (100, "input_number.value_100"))
async def test_if_not_fires_if_entity_not_match(hass, calls, below):
"""Test if not fired with non matching entity."""
assert await async_setup_component(
hass,
@ -495,7 +560,7 @@ async def test_if_not_fires_if_entity_not_match(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.another_entity",
"below": 100,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -507,7 +572,8 @@ async def test_if_not_fires_if_entity_not_match(hass, calls):
assert len(calls) == 0
async def test_if_fires_on_entity_change_below_with_attribute(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_fires_on_entity_change_below_with_attribute(hass, calls, below):
"""Test attributes change."""
hass.states.async_set("test.entity", 11, {"test_attribute": 11})
await hass.async_block_till_done()
@ -520,7 +586,7 @@ async def test_if_fires_on_entity_change_below_with_attribute(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -532,7 +598,10 @@ async def test_if_fires_on_entity_change_below_with_attribute(hass, calls):
assert len(calls) == 1
async def test_if_not_fires_on_entity_change_not_below_with_attribute(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_not_fires_on_entity_change_not_below_with_attribute(
hass, calls, below
):
"""Test attributes."""
assert await async_setup_component(
hass,
@ -542,7 +611,7 @@ async def test_if_not_fires_on_entity_change_not_below_with_attribute(hass, call
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -554,7 +623,8 @@ async def test_if_not_fires_on_entity_change_not_below_with_attribute(hass, call
assert len(calls) == 0
async def test_if_fires_on_attribute_change_with_attribute_below(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_fires_on_attribute_change_with_attribute_below(hass, calls, below):
"""Test attributes change."""
hass.states.async_set("test.entity", "entity", {"test_attribute": 11})
await hass.async_block_till_done()
@ -568,7 +638,7 @@ async def test_if_fires_on_attribute_change_with_attribute_below(hass, calls):
"platform": "numeric_state",
"entity_id": "test.entity",
"value_template": "{{ state.attributes.test_attribute }}",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -580,7 +650,10 @@ async def test_if_fires_on_attribute_change_with_attribute_below(hass, calls):
assert len(calls) == 1
async def test_if_not_fires_on_attribute_change_with_attribute_not_below(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_not_fires_on_attribute_change_with_attribute_not_below(
hass, calls, below
):
"""Test attributes change."""
assert await async_setup_component(
hass,
@ -591,7 +664,7 @@ async def test_if_not_fires_on_attribute_change_with_attribute_not_below(hass, c
"platform": "numeric_state",
"entity_id": "test.entity",
"value_template": "{{ state.attributes.test_attribute }}",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -603,7 +676,8 @@ async def test_if_not_fires_on_attribute_change_with_attribute_not_below(hass, c
assert len(calls) == 0
async def test_if_not_fires_on_entity_change_with_attribute_below(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_not_fires_on_entity_change_with_attribute_below(hass, calls, below):
"""Test attributes change."""
assert await async_setup_component(
hass,
@ -614,7 +688,7 @@ async def test_if_not_fires_on_entity_change_with_attribute_below(hass, calls):
"platform": "numeric_state",
"entity_id": "test.entity",
"value_template": "{{ state.attributes.test_attribute }}",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -626,7 +700,10 @@ async def test_if_not_fires_on_entity_change_with_attribute_below(hass, calls):
assert len(calls) == 0
async def test_if_not_fires_on_entity_change_with_not_attribute_below(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_if_not_fires_on_entity_change_with_not_attribute_below(
hass, calls, below
):
"""Test attributes change."""
assert await async_setup_component(
hass,
@ -637,7 +714,7 @@ async def test_if_not_fires_on_entity_change_with_not_attribute_below(hass, call
"platform": "numeric_state",
"entity_id": "test.entity",
"value_template": "{{ state.attributes.test_attribute }}",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -649,7 +726,10 @@ async def test_if_not_fires_on_entity_change_with_not_attribute_below(hass, call
assert len(calls) == 0
async def test_fires_on_attr_change_with_attribute_below_and_multiple_attr(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_fires_on_attr_change_with_attribute_below_and_multiple_attr(
hass, calls, below
):
"""Test attributes change."""
hass.states.async_set(
"test.entity", "entity", {"test_attribute": 11, "not_test_attribute": 11}
@ -664,7 +744,7 @@ async def test_fires_on_attr_change_with_attribute_below_and_multiple_attr(hass,
"platform": "numeric_state",
"entity_id": "test.entity",
"value_template": "{{ state.attributes.test_attribute }}",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -678,7 +758,8 @@ async def test_fires_on_attr_change_with_attribute_below_and_multiple_attr(hass,
assert len(calls) == 1
async def test_template_list(hass, calls):
@pytest.mark.parametrize("below", (10, "input_number.value_10"))
async def test_template_list(hass, calls, below):
"""Test template list."""
hass.states.async_set("test.entity", "entity", {"test_attribute": [11, 15, 11]})
await hass.async_block_till_done()
@ -691,7 +772,7 @@ async def test_template_list(hass, calls):
"platform": "numeric_state",
"entity_id": "test.entity",
"value_template": "{{ state.attributes.test_attribute[2] }}",
"below": 10,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -703,7 +784,8 @@ async def test_template_list(hass, calls):
assert len(calls) == 1
async def test_template_string(hass, calls):
@pytest.mark.parametrize("below", (10.0, "input_number.value_10"))
async def test_template_string(hass, calls, below):
"""Test template string."""
assert await async_setup_component(
hass,
@ -714,7 +796,7 @@ async def test_template_string(hass, calls):
"platform": "numeric_state",
"entity_id": "test.entity",
"value_template": "{{ state.attributes.test_attribute | multiply(10) }}",
"below": 10,
"below": below,
},
"action": {
"service": "test.automation",
@ -742,7 +824,7 @@ async def test_template_string(hass, calls):
assert len(calls) == 1
assert (
calls[0].data["some"]
== "numeric_state - test.entity - 10.0 - None - test state 1 - test state 2"
== f"numeric_state - test.entity - {below} - None - test state 1 - test state 2"
)
@ -771,7 +853,16 @@ async def test_not_fires_on_attr_change_with_attr_not_below_multiple_attr(hass,
assert len(calls) == 0
async def test_if_action(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_action(hass, calls, above, below):
"""Test if action."""
entity_id = "domain.test_entity"
assert await async_setup_component(
@ -783,8 +874,8 @@ async def test_if_action(hass, calls):
"condition": {
"condition": "numeric_state",
"entity_id": entity_id,
"above": 8,
"below": 12,
"above": above,
"below": below,
},
"action": {"service": "test.automation"},
}
@ -810,7 +901,16 @@ async def test_if_action(hass, calls):
assert len(calls) == 2
async def test_if_fails_setup_bad_for(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_fails_setup_bad_for(hass, calls, above, below):
"""Test for setup failure for bad for."""
hass.states.async_set("test.entity", 5)
await hass.async_block_till_done()
@ -823,8 +923,8 @@ async def test_if_fails_setup_bad_for(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": {"invalid": 5},
},
"action": {"service": "homeassistant.turn_on"},
@ -857,7 +957,16 @@ async def test_if_fails_setup_for_without_above_below(hass, calls):
)
async def test_if_not_fires_on_entity_change_with_for(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_not_fires_on_entity_change_with_for(hass, calls, above, below):
"""Test for not firing on entity change with for."""
assert await async_setup_component(
hass,
@ -867,8 +976,8 @@ async def test_if_not_fires_on_entity_change_with_for(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": {"seconds": 5},
},
"action": {"service": "test.automation"},
@ -885,7 +994,18 @@ async def test_if_not_fires_on_entity_change_with_for(hass, calls):
assert len(calls) == 0
async def test_if_not_fires_on_entities_change_with_for_after_stop(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_not_fires_on_entities_change_with_for_after_stop(
hass, calls, above, below
):
"""Test for not firing on entities change with for after stop."""
hass.states.async_set("test.entity_1", 0)
hass.states.async_set("test.entity_2", 0)
@ -899,8 +1019,8 @@ async def test_if_not_fires_on_entities_change_with_for_after_stop(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": ["test.entity_1", "test.entity_2"],
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": {"seconds": 5},
},
"action": {"service": "test.automation"},
@ -932,7 +1052,18 @@ async def test_if_not_fires_on_entities_change_with_for_after_stop(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_entity_change_with_for_attribute_change(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_fires_on_entity_change_with_for_attribute_change(
hass, calls, above, below
):
"""Test for firing on entity change with for and attribute change."""
hass.states.async_set("test.entity", 0)
await hass.async_block_till_done()
@ -945,8 +1076,8 @@ async def test_if_fires_on_entity_change_with_for_attribute_change(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": {"seconds": 5},
},
"action": {"service": "test.automation"},
@ -970,7 +1101,16 @@ async def test_if_fires_on_entity_change_with_for_attribute_change(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_entity_change_with_for(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_fires_on_entity_change_with_for(hass, calls, above, below):
"""Test for firing on entity change with for."""
hass.states.async_set("test.entity", 0)
await hass.async_block_till_done()
@ -983,8 +1123,8 @@ async def test_if_fires_on_entity_change_with_for(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": {"seconds": 5},
},
"action": {"service": "test.automation"},
@ -999,7 +1139,8 @@ async def test_if_fires_on_entity_change_with_for(hass, calls):
assert len(calls) == 1
async def test_wait_template_with_trigger(hass, calls):
@pytest.mark.parametrize("above", (10, "input_number.value_10"))
async def test_wait_template_with_trigger(hass, calls, above):
"""Test using wait template with 'trigger.entity_id'."""
hass.states.async_set("test.entity", "0")
await hass.async_block_till_done()
@ -1012,7 +1153,7 @@ async def test_wait_template_with_trigger(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 10,
"above": above,
},
"action": [
{"wait_template": "{{ states(trigger.entity_id) | int < 10 }}"},
@ -1039,7 +1180,16 @@ async def test_wait_template_with_trigger(hass, calls):
assert "numeric_state - test.entity - 12" == calls[0].data["some"]
async def test_if_fires_on_entities_change_no_overlap(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_fires_on_entities_change_no_overlap(hass, calls, above, below):
"""Test for firing on entities change with no overlap."""
hass.states.async_set("test.entity_1", 0)
hass.states.async_set("test.entity_2", 0)
@ -1053,8 +1203,8 @@ async def test_if_fires_on_entities_change_no_overlap(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": ["test.entity_1", "test.entity_2"],
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": {"seconds": 5},
},
"action": {
@ -1086,7 +1236,16 @@ async def test_if_fires_on_entities_change_no_overlap(hass, calls):
assert calls[1].data["some"] == "test.entity_2"
async def test_if_fires_on_entities_change_overlap(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_fires_on_entities_change_overlap(hass, calls, above, below):
"""Test for firing on entities change with overlap."""
hass.states.async_set("test.entity_1", 0)
hass.states.async_set("test.entity_2", 0)
@ -1100,8 +1259,8 @@ async def test_if_fires_on_entities_change_overlap(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": ["test.entity_1", "test.entity_2"],
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": {"seconds": 5},
},
"action": {
@ -1144,7 +1303,16 @@ async def test_if_fires_on_entities_change_overlap(hass, calls):
assert calls[1].data["some"] == "test.entity_2"
async def test_if_fires_on_change_with_for_template_1(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_fires_on_change_with_for_template_1(hass, calls, above, below):
"""Test for firing on change with for template."""
hass.states.async_set("test.entity", 0)
await hass.async_block_till_done()
@ -1157,8 +1325,8 @@ async def test_if_fires_on_change_with_for_template_1(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": {"seconds": "{{ 5 }}"},
},
"action": {"service": "test.automation"},
@ -1174,7 +1342,16 @@ async def test_if_fires_on_change_with_for_template_1(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_change_with_for_template_2(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_fires_on_change_with_for_template_2(hass, calls, above, below):
"""Test for firing on change with for template."""
hass.states.async_set("test.entity", 0)
await hass.async_block_till_done()
@ -1187,8 +1364,8 @@ async def test_if_fires_on_change_with_for_template_2(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": "{{ 5 }}",
},
"action": {"service": "test.automation"},
@ -1204,7 +1381,16 @@ async def test_if_fires_on_change_with_for_template_2(hass, calls):
assert len(calls) == 1
async def test_if_fires_on_change_with_for_template_3(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_fires_on_change_with_for_template_3(hass, calls, above, below):
"""Test for firing on change with for template."""
hass.states.async_set("test.entity", 0)
await hass.async_block_till_done()
@ -1217,8 +1403,8 @@ async def test_if_fires_on_change_with_for_template_3(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": "00:00:{{ 5 }}",
},
"action": {"service": "test.automation"},
@ -1234,7 +1420,16 @@ async def test_if_fires_on_change_with_for_template_3(hass, calls):
assert len(calls) == 1
async def test_invalid_for_template(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_invalid_for_template(hass, calls, above, below):
"""Test for invalid for template."""
hass.states.async_set("test.entity", 0)
await hass.async_block_till_done()
@ -1247,8 +1442,8 @@ async def test_invalid_for_template(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": "{{ five }}",
},
"action": {"service": "test.automation"},
@ -1262,7 +1457,18 @@ async def test_invalid_for_template(hass, calls):
assert mock_logger.error.called
async def test_if_fires_on_entities_change_overlap_for_template(hass, calls):
@pytest.mark.parametrize(
"above, below",
(
(8, 12),
(8, "input_number.value_12"),
("input_number.value_8", 12),
("input_number.value_8", "input_number.value_12"),
),
)
async def test_if_fires_on_entities_change_overlap_for_template(
hass, calls, above, below
):
"""Test for firing on entities change with overlap and for template."""
hass.states.async_set("test.entity_1", 0)
hass.states.async_set("test.entity_2", 0)
@ -1276,8 +1482,8 @@ async def test_if_fires_on_entities_change_overlap_for_template(hass, calls):
"trigger": {
"platform": "numeric_state",
"entity_id": ["test.entity_1", "test.entity_2"],
"above": 8,
"below": 12,
"above": above,
"below": below,
"for": '{{ 5 if trigger.entity_id == "test.entity_1"'
" else 10 }}",
},
@ -1335,7 +1541,30 @@ def test_below_above():
)
async def test_attribute_if_fires_on_entity_change_with_both_filters(hass, calls):
def test_schema_input_number():
"""Test input_number only is accepted for above/below."""
with pytest.raises(vol.Invalid):
numeric_state_trigger.TRIGGER_SCHEMA(
{
"platform": "numeric_state",
"above": "input_datetime.some_input",
"below": 1000,
}
)
with pytest.raises(vol.Invalid):
numeric_state_trigger.TRIGGER_SCHEMA(
{
"platform": "numeric_state",
"below": "input_datetime.some_input",
"above": 1200,
}
)
@pytest.mark.parametrize("above", (3, "input_number.value_3"))
async def test_attribute_if_fires_on_entity_change_with_both_filters(
hass, calls, above
):
"""Test for firing if both filters are match attribute."""
hass.states.async_set("test.entity", "bla", {"test-measurement": 1})
@ -1347,7 +1576,7 @@ async def test_attribute_if_fires_on_entity_change_with_both_filters(hass, calls
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 3,
"above": above,
"attribute": "test-measurement",
},
"action": {"service": "test.automation"},
@ -1361,8 +1590,9 @@ async def test_attribute_if_fires_on_entity_change_with_both_filters(hass, calls
assert len(calls) == 1
@pytest.mark.parametrize("above", (3, "input_number.value_3"))
async def test_attribute_if_not_fires_on_entities_change_with_for_after_stop(
hass, calls
hass, calls, above
):
"""Test for not firing on entity change with for after stop trigger."""
hass.states.async_set("test.entity", "bla", {"test-measurement": 1})
@ -1375,7 +1605,7 @@ async def test_attribute_if_not_fires_on_entities_change_with_for_after_stop(
"trigger": {
"platform": "numeric_state",
"entity_id": "test.entity",
"above": 3,
"above": above,
"attribute": "test-measurement",
"for": 5,
},