diff --git a/src/card-controller/conditions-manager.ts b/src/card-controller/conditions-manager.ts index 641a8e71..ddce4544 100644 --- a/src/card-controller/conditions-manager.ts +++ b/src/card-controller/conditions-manager.ts @@ -212,8 +212,10 @@ export class ConditionsManager { }; const conditions = getAllConditions(); - this._hasHAStateConditions = conditions.some((conditionObj) => - ['state', 'numeric_state', 'user'].includes(conditionObj.condition), + this._hasHAStateConditions = conditions.some( + (conditionObj) => + !conditionObj.condition || + ['state', 'numeric_state', 'user'].includes(conditionObj.condition), ); conditions.forEach((conditionObj) => { if (conditionObj.condition === 'screen') { @@ -263,16 +265,7 @@ export class ConditionsManager { }; switch (conditionObj.condition) { - case 'view': - return !!state?.view && conditionObj.views.includes(state.view); - case 'fullscreen': - return ( - state.fullscreen !== undefined && conditionObj.fullscreen === state.fullscreen - ); - case 'expand': - return state.expand !== undefined && conditionObj.expand === state.expand; - case 'camera': - return !!state.camera && conditionObj.cameras.includes(state.camera); + case undefined: case 'state': return ( !!state.state && @@ -289,6 +282,16 @@ export class ConditionsManager { ) : conditionObj.state_not !== state.state[conditionObj.entity].state)))) ); + case 'view': + return !!state?.view && conditionObj.views.includes(state.view); + case 'fullscreen': + return ( + state.fullscreen !== undefined && conditionObj.fullscreen === state.fullscreen + ); + case 'expand': + return state.expand !== undefined && conditionObj.expand === state.expand; + case 'camera': + return !!state.camera && conditionObj.cameras.includes(state.camera); case 'numeric_state': return ( !!state.state && diff --git a/src/config/types.ts b/src/config/types.ts index 2e9b1f1c..07bedb6c 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -518,7 +518,10 @@ const imageSchema = elementsBaseSchema.extend({ // https://www.home-assistant.io/dashboards/conditional/#state const stateConditionSchema = z.object({ - condition: z.literal('state'), + // If the condition is not specified, a state condition is assumed. This + // allows the syntax to match a picture elements conditional: + // https://www.home-assistant.io/dashboards/picture-elements/#conditional-element + condition: z.literal('state').optional(), entity: z.string(), state: z.string().or(z.string().array()).optional(), state_not: z.string().or(z.string().array()).optional(), diff --git a/tests/card-controller/conditions-manager.test.ts b/tests/card-controller/conditions-manager.test.ts index 1a527259..aa1e9497 100644 --- a/tests/card-controller/conditions-manager.test.ts +++ b/tests/card-controller/conditions-manager.test.ts @@ -457,20 +457,37 @@ describe('ConditionsManager', () => { expect(manager.hasHAStateConditions()).toBeFalsy(); }); - it('with HA state conditions', () => { - const api = createCardAPI(); - const numericConfig = createSuitableConfig([ - { - condition: 'state' as const, - entity: 'binary_sensor.foo', - state: 'on', - }, - ]); - vi.mocked(api.getConfigManager().getConfig).mockReturnValue(numericConfig); - const manager = new ConditionsManager(api); - manager.setConditionsFromConfig(); + describe('with HA state conditions', () => { + it('explicitly stated', () => { + const api = createCardAPI(); + const numericConfig = createSuitableConfig([ + { + condition: 'state' as const, + entity: 'binary_sensor.foo', + state: 'on', + }, + ]); + vi.mocked(api.getConfigManager().getConfig).mockReturnValue(numericConfig); + const manager = new ConditionsManager(api); + manager.setConditionsFromConfig(); - expect(manager.hasHAStateConditions()).toBeTruthy(); + expect(manager.hasHAStateConditions()).toBeTruthy(); + }); + + it('implicitly assumed', () => { + const api = createCardAPI(); + const numericConfig = createSuitableConfig([ + { + entity: 'binary_sensor.foo', + state: 'on', + }, + ]); + vi.mocked(api.getConfigManager().getConfig).mockReturnValue(numericConfig); + const manager = new ConditionsManager(api); + manager.setConditionsFromConfig(); + + expect(manager.hasHAStateConditions()).toBeTruthy(); + }); }); it('with HA numeric_state conditions', () => { @@ -657,6 +674,23 @@ describe('ConditionsManager', () => { }); expect(manager.evaluateConditions(conditions)).toBeTruthy(); }); + + it('implicit state condition', () => { + const manager = new ConditionsManager(createCardAPI()); + const conditions = [ + { + entity: 'binary_sensor.foo', + state: 'on', + }, + ]; + expect(manager.evaluateConditions(conditions)).toBeFalsy(); + manager.setState({ state: { 'binary_sensor.foo': createStateEntity() } }); + expect(manager.evaluateConditions(conditions)).toBeTruthy(); + manager.setState({ + state: { 'binary_sensor.foo': createStateEntity({ state: 'off' }) }, + }); + expect(manager.evaluateConditions(conditions)).toBeFalsy(); + }); }); describe('with numeric state condition', () => {