diff --git a/src/condition-trigger/conditions/conditions/state.ts b/src/condition-trigger/conditions/conditions/state.ts index 6e1582e1..c50c47c2 100644 --- a/src/condition-trigger/conditions/conditions/state.ts +++ b/src/condition-trigger/conditions/conditions/state.ts @@ -7,10 +7,13 @@ import type { ConditionEvaluator, ConditionOfType, EvaluatorContext } from './ty // Home Assistant resolves an expected value that names an `input_*` helper to // that helper's current state (its Lovelace state-condition behavior), on both // the state and the attribute path; only these helper domains are resolved. -// Regexp directly from: +// Matches the same entity IDs as the regexp in Home Assistant: // https://github.com/home-assistant/core/blob/dev/homeassistant/helpers/condition.py +// That regexp rejects a trailing `_` with a lookbehind, which Safari before +// 16.4 fails to parse (taking the whole card down), so the leading and trailing +// character are spelled out here instead. const INPUT_ENTITY_ID = - /^input_(?:select|text|number|boolean|datetime)\.(?!.+__)(?!_)[\da-z_]+(? typeof value === 'string' && INPUT_ENTITY_ID.test(value); diff --git a/tests/condition-trigger/conditions/conditions/state.test.ts b/tests/condition-trigger/conditions/conditions/state.test.ts index e3217120..c0a82547 100644 --- a/tests/condition-trigger/conditions/conditions/state.test.ts +++ b/tests/condition-trigger/conditions/conditions/state.test.ts @@ -734,6 +734,34 @@ describe('state condition', () => { ).toBeFalsy(); }); + it.each([ + ['input_text.expected', true], + ['input_text.a_1', true], + ['input_text.', false], + ['input_text._expected', false], + ['input_text.__expected', false], + ['input_text.expected_', false], + ['input_text.expected__name', false], + ])('should resolve only a valid input helper ID: %s', (entityID, shouldResolve) => { + const evaluator = createConditionEvaluator( + { + condition: 'state' as const, + entity_id: 'binary_sensor.foo', + state: entityID, + }, + createEvaluatorContext(), + ); + + expect( + evaluator.evaluate({ + hass: createHASS({ + 'binary_sensor.foo': createStateEntity({ state: 'armed' }), + [entityID]: createStateEntity({ state: 'armed' }), + }), + }).result, + ).toBe(shouldResolve); + }); + it('should not resolve a non-input entity name', () => { // Only `input_*` helpers are resolved; other entity names compare literally. const evaluator = createConditionEvaluator(