async def test_capability_pause_vacuum(hass): state = State('vacuum.test', STATE_ON) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_PAUSE) for s in vacuum.STATES: state = State('vacuum.test', s, {ATTR_SUPPORTED_FEATURES: vacuum.SUPPORT_PAUSE}) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_PAUSE) assert cap.retrievable assert cap.parameters() == {'instance': TOGGLE_INSTANCE_PAUSE} assert cap.get_value() is False state = State('vacuum.test', vacuum.STATE_PAUSED, {ATTR_SUPPORTED_FEATURES: vacuum.SUPPORT_PAUSE}) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_PAUSE) assert cap.get_value() is True on_calls = async_mock_service(hass, vacuum.DOMAIN, vacuum.SERVICE_PAUSE) await cap.set_state(BASIC_DATA, {'value': True}) assert len(on_calls) == 1 assert on_calls[0].data == {ATTR_ENTITY_ID: state.entity_id} off_calls = async_mock_service(hass, vacuum.DOMAIN, vacuum.SERVICE_START) await cap.set_state(BASIC_DATA, {'value': False}) assert len(off_calls) == 1 assert off_calls[0].data == {ATTR_ENTITY_ID: state.entity_id}
async def test_capability_mute(hass): state = State('media_player.test', STATE_ON) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_MUTE) state = State('media_player.test', STATE_ON) config = MockConfig( entity_config={state.entity_id: { 'features': ['volume_mute'] }}) assert_exact_one_capability(hass, config, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_MUTE) state = State('media_player.test', STATE_ON, {ATTR_SUPPORTED_FEATURES: media_player.SUPPORT_VOLUME_MUTE}) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_MUTE) assert cap.retrievable is False assert cap.parameters() == {'instance': TOGGLE_INSTANCE_MUTE} assert cap.get_value() is False calls = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_MUTE) await cap.set_state(BASIC_DATA, {'value': True}) await cap.set_state(BASIC_DATA, {'value': False}) assert len(calls) == 2 assert calls[0].data[ATTR_ENTITY_ID] == state.entity_id assert calls[0].data[media_player.ATTR_MEDIA_VOLUME_MUTED] is True assert calls[1].data[ATTR_ENTITY_ID] == state.entity_id assert calls[1].data[media_player.ATTR_MEDIA_VOLUME_MUTED] is False state = State( 'media_player.test', STATE_ON, { ATTR_SUPPORTED_FEATURES: media_player.SUPPORT_VOLUME_MUTE, media_player.ATTR_MEDIA_VOLUME_MUTED: True }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_MUTE) assert cap.retrievable assert cap.get_value() is True calls = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_MUTE) await cap.set_state(BASIC_DATA, {'value': True}) await cap.set_state(BASIC_DATA, {'value': False}) assert len(calls) == 2 assert calls[0].data[ATTR_ENTITY_ID] == state.entity_id assert calls[0].data[media_player.ATTR_MEDIA_VOLUME_MUTED] is True assert calls[1].data[ATTR_ENTITY_ID] == state.entity_id assert calls[1].data[media_player.ATTR_MEDIA_VOLUME_MUTED] is False
async def test_capability_range_volume_only_relative(hass, precision): state = State('media_player.test', STATE_ON, {ATTR_SUPPORTED_FEATURES: media_player.SUPPORT_VOLUME_STEP}) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_VOLUME) assert not cap.support_random_access entity_config = {} if precision: entity_config = { const.CONF_ENTITY_RANGE: { const.CONF_ENTITY_RANGE_PRECISION: precision } } config = MockConfig(entity_config={state.entity_id: entity_config}) cap = get_exact_one_capability(hass, config, state, CAPABILITIES_RANGE, RANGE_INSTANCE_VOLUME) calls_up = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_UP) with pytest.raises(SmartHomeError) as e: await cap.set_state(BASIC_DATA, {'value': 15}) assert e.value.code == const.ERR_INVALID_VALUE await cap.set_state(BASIC_DATA, {'value': 3, 'relative': True}) assert len(calls_up) == 3 for i in range(0, len(calls_up)): assert calls_up[i].data[ATTR_ENTITY_ID] == state.entity_id calls_down = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_DOWN) await cap.set_state(BASIC_DATA, {'value': -2, 'relative': True}) assert len(calls_down) == 2 for i in range(0, len(calls_down)): assert calls_down[i].data[ATTR_ENTITY_ID] == state.entity_id calls_one_up = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_UP) await cap.set_state(BASIC_DATA, {'value': 1, 'relative': True}) assert len(calls_one_up) == (precision or 1) for i in range(0, precision or 1): assert calls_one_up[i].data[ATTR_ENTITY_ID] == state.entity_id calls_one_down = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_DOWN) await cap.set_state(BASIC_DATA, {'value': -1, 'relative': True}) assert len(calls_one_down) == (precision or 1) for i in range(0, precision or 1): assert calls_one_down[i].data[ATTR_ENTITY_ID] == state.entity_id
async def test_capability_custom_mode(hass): state = State('switch.test', STATE_ON) cap = CustomModeCapability(hass, BASIC_CONFIG, state, const.MODE_INSTANCE_CLEANUP_MODE, {const.CONF_ENTITY_CUSTOM_MODE_SET_MODE: None}) assert not cap.supported() state = State('switch.test', 'mode_1', {}) hass.states.async_set(state.entity_id, state.state) config = MockConfig( entity_config={ state.entity_id: { const.CONF_ENTITY_MODE_MAP: { const.MODE_INSTANCE_CLEANUP_MODE: { const.MODE_INSTANCE_MODE_ONE: ['mode_1'], const.MODE_INSTANCE_MODE_TWO: ['mode_2'], } } } }) cap = CustomModeCapability( hass, config, state, const.MODE_INSTANCE_CLEANUP_MODE, { const.CONF_ENTITY_CUSTOM_MODE_SET_MODE: { CONF_SERVICE: 'test.set_mode', ATTR_ENTITY_ID: 'switch.test', CONF_SERVICE_DATA: { 'service_mode': dynamic_template('mode: {{ mode }}') } }, }) assert cap.supported() assert cap.retrievable is False assert cap.modes_list_attribute is None assert cap.get_value() is None cap = CustomModeCapability( hass, config, state, const.MODE_INSTANCE_CLEANUP_MODE, { const.CONF_ENTITY_CUSTOM_CAPABILITY_STATE_ENTITY_ID: state.entity_id, const.CONF_ENTITY_CUSTOM_MODE_SET_MODE: { CONF_SERVICE: 'test.set_mode', ATTR_ENTITY_ID: 'switch.test', CONF_SERVICE_DATA: { 'service_mode': dynamic_template('mode: {{ mode }}') } }, }) assert cap.supported() assert cap.retrievable assert cap.modes_list_attribute is None assert cap.get_value() == 'one' calls = async_mock_service(hass, 'test', 'set_mode') await cap.set_state(BASIC_DATA, {'value': 'one'}) assert len(calls) == 1 assert calls[0].data == { 'service_mode': 'mode: mode_1', ATTR_ENTITY_ID: 'switch.test' }
async def test_capability_range_temperature_water_heater(hass): state = State('water_heater.test', water_heater.STATE_OFF) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_TEMPERATURE) state = State( 'water_heater.test', water_heater.STATE_OFF, { ATTR_SUPPORTED_FEATURES: water_heater.SUPPORT_TARGET_TEMPERATURE, water_heater.ATTR_MIN_TEMP: 30, water_heater.ATTR_MAX_TEMP: 90, }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_TEMPERATURE) assert cap.retrievable assert cap.support_random_access assert cap.parameters() == { 'instance': 'temperature', 'random_access': True, 'range': { 'max': 90, 'min': 30, 'precision': 0.5 }, 'unit': 'unit.temperature.celsius', } assert not cap.get_value() state = State( 'water_heater.test', water_heater.STATE_ELECTRIC, { ATTR_SUPPORTED_FEATURES: water_heater.SUPPORT_TARGET_TEMPERATURE, water_heater.ATTR_MIN_TEMP: 30, water_heater.ATTR_MAX_TEMP: 90, water_heater.ATTR_TEMPERATURE: 50 }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_TEMPERATURE) assert cap.retrievable assert cap.support_random_access assert cap.get_value() == 50 calls = async_mock_service(hass, water_heater.DOMAIN, water_heater.SERVICE_SET_TEMPERATURE) await cap.set_state(BASIC_DATA, {'value': 20}) await cap.set_state(BASIC_DATA, {'value': 100}) await cap.set_state(BASIC_DATA, {'value': 50}) await cap.set_state(BASIC_DATA, {'value': 15, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -20, 'relative': True}) assert len(calls) == 5 for i in range(0, len(calls)): assert calls[i].data[ATTR_ENTITY_ID] == state.entity_id assert calls[0].data[water_heater.ATTR_TEMPERATURE] == 20 assert calls[1].data[water_heater.ATTR_TEMPERATURE] == 100 assert calls[2].data[water_heater.ATTR_TEMPERATURE] == 50 assert calls[3].data[water_heater.ATTR_TEMPERATURE] == 65 assert calls[4].data[water_heater.ATTR_TEMPERATURE] == 30
async def test_capability_range_channel_set_random(hass, caplog): state = State('media_player.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: media_player.SUPPORT_PLAY_MEDIA, }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_CHANNEL) assert cap.retrievable is False assert cap.support_random_access is False state = State( 'media_player.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: media_player.SUPPORT_PLAY_MEDIA, ATTR_DEVICE_CLASS: media_player.DEVICE_CLASS_RECEIVER }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_CHANNEL) assert cap.retrievable is False assert cap.support_random_access is False state = State( 'media_player.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: media_player.SUPPORT_PLAY_MEDIA, ATTR_DEVICE_CLASS: media_player.DEVICE_CLASS_TV }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_CHANNEL) assert cap.retrievable assert cap.support_random_access assert cap.parameters() == { 'instance': 'channel', 'random_access': True, 'range': { 'max': 999, 'min': 0, 'precision': 1 }, } assert cap.get_value() is None calls_set = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_PLAY_MEDIA) await cap.set_state(BASIC_DATA, {'value': 15}) await hass.async_block_till_done() assert len(calls_set) == 1 assert calls_set[0].data == { ATTR_ENTITY_ID: state.entity_id, media_player.ATTR_MEDIA_CONTENT_ID: 15, media_player.ATTR_MEDIA_CONTENT_TYPE: media_player.const.MEDIA_TYPE_CHANNEL } with pytest.raises(SmartHomeError) as e: await cap.set_state(BASIC_DATA, {'value': 1, 'relative': True}) assert e.value.code == const.ERR_NOT_SUPPORTED_IN_CURRENT_MODE with pytest.raises(SmartHomeError) as e: await cap.set_state(BASIC_DATA, {'value': -1, 'relative': True}) assert e.value.code == const.ERR_NOT_SUPPORTED_IN_CURRENT_MODE
async def test_capability_custom_toggle(hass): state = State('switch.test', STATE_ON) cap = CustomToggleCapability( hass, BASIC_CONFIG, state, 'test_toggle', { const.CONF_ENTITY_CUSTOM_TOGGLE_TURN_ON: None, const.CONF_ENTITY_CUSTOM_TOGGLE_TURN_OFF: None }) assert cap.supported() assert cap.retrievable is False assert cap.get_value() is None state = State('switch.test', STATE_ON, {}) hass.states.async_set(state.entity_id, state.state) cap = CustomToggleCapability( hass, BASIC_CONFIG, state, 'test_toggle', { const.CONF_ENTITY_CUSTOM_CAPABILITY_STATE_ENTITY_ID: state.entity_id, const.CONF_ENTITY_CUSTOM_TOGGLE_TURN_ON: { CONF_SERVICE: 'test.turn_on', ATTR_ENTITY_ID: 'switch.test1', }, const.CONF_ENTITY_CUSTOM_TOGGLE_TURN_OFF: { CONF_SERVICE: 'test.turn_off', ATTR_ENTITY_ID: 'switch.test2', }, }) assert cap.supported() assert cap.retrievable assert cap.get_value() is True hass.states.async_set(state.entity_id, STATE_OFF) assert cap.get_value() is False calls_on = async_mock_service(hass, 'test', 'turn_on') await cap.set_state(BASIC_DATA, {'value': True}) assert len(calls_on) == 1 assert calls_on[0].data == {ATTR_ENTITY_ID: 'switch.test1'} calls_off = async_mock_service(hass, 'test', 'turn_off') await cap.set_state(BASIC_DATA, {'value': False}) assert len(calls_off) == 1 assert calls_off[0].data == {ATTR_ENTITY_ID: 'switch.test2'}
async def test_yandex_entity_execute(hass): state = State('switch.test', STATE_ON) entity = YandexEntity(hass, BASIC_CONFIG, state) with pytest.raises(SmartHomeError) as e: await entity.execute(BASIC_DATA, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_PAUSE, {'value': True}) assert e.value.code == ERR_NOT_SUPPORTED_IN_CURRENT_MODE off_calls = async_mock_service(hass, state.domain, SERVICE_TURN_OFF) await entity.execute(BASIC_DATA, CAPABILITIES_ONOFF, 'on', {'value': False}) assert len(off_calls) == 1 assert off_calls[0].data == {ATTR_ENTITY_ID: state.entity_id}
async def test_capability_range_channel_set_relative(hass, features, device_class): state = State( 'media_player.test', STATE_OFF, {ATTR_SUPPORTED_FEATURES: media_player.SUPPORT_PREVIOUS_TRACK}) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_CHANNEL) state = State('media_player.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: features, ATTR_DEVICE_CLASS: device_class }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_CHANNEL) if device_class == media_player.DEVICE_CLASS_TV: assert cap.retrievable is bool(features & media_player.SUPPORT_PLAY_MEDIA) assert cap.support_random_access is bool( features & media_player.SUPPORT_PLAY_MEDIA) else: assert not cap.retrievable assert not cap.support_random_access assert cap.parameters() == { 'instance': 'channel', 'random_access': False } assert cap.get_value() is None calls_up = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_MEDIA_NEXT_TRACK) await cap.set_state(BASIC_DATA, {'value': 1, 'relative': True}) assert len(calls_up) == 1 assert calls_up[0].data == {ATTR_ENTITY_ID: state.entity_id} calls_down = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_MEDIA_PREVIOUS_TRACK) await cap.set_state(BASIC_DATA, {'value': -1, 'relative': True}) assert len(calls_down) == 1 assert calls_down[0].data == {ATTR_ENTITY_ID: state.entity_id}
async def test_capability_pause_media_player(hass): state = State('media_player.test', STATE_ON) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_PAUSE) for s in [media_player.STATE_IDLE, media_player.STATE_OFF]: state = State( 'media_player.test', s, { ATTR_SUPPORTED_FEATURES: media_player.SUPPORT_PAUSE | media_player.SUPPORT_PLAY }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_PAUSE) assert cap.retrievable assert cap.parameters() == {'instance': TOGGLE_INSTANCE_PAUSE} assert cap.get_value() is True state = State( 'media_player.test', media_player.STATE_PLAYING, { ATTR_SUPPORTED_FEATURES: media_player.SUPPORT_PAUSE | media_player.SUPPORT_PLAY }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_PAUSE) assert cap.get_value() is False on_calls = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_MEDIA_PAUSE) await cap.set_state(BASIC_DATA, {'value': True}) assert len(on_calls) == 1 assert on_calls[0].data == {ATTR_ENTITY_ID: state.entity_id} off_calls = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_MEDIA_PLAY) await cap.set_state(BASIC_DATA, {'value': False}) assert len(off_calls) == 1 assert off_calls[0].data == {ATTR_ENTITY_ID: state.entity_id}
async def test_capability_range_volume_support_random(hass, features): state = State('media_player.test', STATE_OFF) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_VOLUME) state = State('media_player.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: features, }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_VOLUME) assert cap.retrievable assert cap.support_random_access assert cap.parameters() == { 'instance': 'volume', 'random_access': True, 'range': { 'max': 100, 'min': 0, 'precision': 1 }, } assert cap.get_value() is None state = State( 'media_player.test', STATE_ON, { ATTR_SUPPORTED_FEATURES: features, media_player.ATTR_MEDIA_VOLUME_LEVEL: 0.56 }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_VOLUME) assert cap.get_value() == 56 calls = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_SET) await cap.set_state(BASIC_DATA, {'value': 0}) await cap.set_state(BASIC_DATA, {'value': 34}) await cap.set_state(BASIC_DATA, {'value': 126}) await cap.set_state(BASIC_DATA, {'value': 30, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -10, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -60, 'relative': True}) assert len(calls) == 6 for i in range(0, len(calls)): assert calls[i].data[ATTR_ENTITY_ID] == state.entity_id assert calls[0].data[media_player.ATTR_MEDIA_VOLUME_LEVEL] == 0 assert calls[1].data[media_player.ATTR_MEDIA_VOLUME_LEVEL] == 0.34 assert calls[2].data[media_player.ATTR_MEDIA_VOLUME_LEVEL] == 1.26 assert calls[3].data[media_player.ATTR_MEDIA_VOLUME_LEVEL] == 0.86 assert calls[4].data[media_player.ATTR_MEDIA_VOLUME_LEVEL] == 0.46
async def test_capability_range_brightness(hass, color_mode): state = State( 'light.test', STATE_ON, { ATTR_SUPPORTED_FEATURES: light.SUPPORT_BRIGHTNESS, light.ATTR_SUPPORTED_COLOR_MODES: [color_mode] }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_BRIGHTNESS) assert cap.retrievable assert cap.support_random_access assert cap.parameters() == { 'instance': 'brightness', 'random_access': True, 'range': { 'max': 100, 'min': 1, 'precision': 1 }, 'unit': 'unit.percent', } assert cap.get_value() is None state = State('light.test', STATE_ON, { light.ATTR_SUPPORTED_COLOR_MODES: [color_mode], light.ATTR_BRIGHTNESS: 128 }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_BRIGHTNESS) assert cap.get_value() == 50 calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON) await cap.set_state(BASIC_DATA, {'value': 0}) await cap.set_state(BASIC_DATA, {'value': 30}) await cap.set_state(BASIC_DATA, {'value': 126}) await cap.set_state(BASIC_DATA, {'value': 30, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -60, 'relative': True}) assert len(calls) == 5 for i in range(0, len(calls)): assert calls[i].data[ATTR_ENTITY_ID] == state.entity_id assert calls[0].data[light.ATTR_BRIGHTNESS_PCT] == 0 assert calls[1].data[light.ATTR_BRIGHTNESS_PCT] == 30 assert calls[2].data[light.ATTR_BRIGHTNESS_PCT] == 126 assert calls[3].data[light.ATTR_BRIGHTNESS_STEP_PCT] == 30 assert calls[4].data[light.ATTR_BRIGHTNESS_STEP_PCT] == -60
async def test_capability_range_humidity_humidifier(hass): state = State('humidifier.test', STATE_OFF, { humidifier.ATTR_MIN_HUMIDITY: 10, humidifier.ATTR_MAX_HUMIDITY: 80, }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_HUMIDITY) assert cap.retrievable assert cap.support_random_access assert cap.parameters() == { 'instance': 'humidity', 'random_access': True, 'range': { 'max': 80, 'min': 10, 'precision': 1 }, 'unit': 'unit.percent', } assert not cap.get_value() state = State( 'humidifier.test', STATE_OFF, { humidifier.ATTR_MIN_HUMIDITY: 10, humidifier.ATTR_MAX_HUMIDITY: 80, humidifier.ATTR_HUMIDITY: 30 }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_HUMIDITY) assert cap.get_value() == 30 calls = async_mock_service(hass, humidifier.DOMAIN, humidifier.SERVICE_SET_HUMIDITY) await cap.set_state(BASIC_DATA, {'value': 20}) await cap.set_state(BASIC_DATA, {'value': 100}) await cap.set_state(BASIC_DATA, {'value': 50}) await cap.set_state(BASIC_DATA, {'value': 15, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -5, 'relative': True}) assert len(calls) == 5 for i in range(0, len(calls)): assert calls[i].data[ATTR_ENTITY_ID] == state.entity_id assert calls[0].data[humidifier.ATTR_HUMIDITY] == 20 assert calls[1].data[humidifier.ATTR_HUMIDITY] == 100 assert calls[2].data[humidifier.ATTR_HUMIDITY] == 50 assert calls[3].data[humidifier.ATTR_HUMIDITY] == 45 assert calls[4].data[humidifier.ATTR_HUMIDITY] == 25
async def test_capability_range_cover(hass): state = State('cover.test', cover.STATE_OPEN) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_OPEN) state = State('cover.test', cover.STATE_OPEN, {ATTR_SUPPORTED_FEATURES: cover.SUPPORT_SET_POSITION}) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_OPEN) assert cap.retrievable assert cap.support_random_access assert cap.parameters() == { 'instance': 'open', 'random_access': True, 'range': { 'max': 100, 'min': 0, 'precision': 1 }, 'unit': 'unit.percent', } assert cap.get_value() is None state = State( 'cover.test', cover.STATE_OPEN, { ATTR_SUPPORTED_FEATURES: cover.SUPPORT_SET_POSITION, cover.ATTR_CURRENT_POSITION: '30', }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_OPEN) assert cap.get_value() == 30 calls = async_mock_service(hass, cover.DOMAIN, cover.SERVICE_SET_COVER_POSITION) await cap.set_state(BASIC_DATA, {'value': 0}) await cap.set_state(BASIC_DATA, {'value': 20}) await cap.set_state(BASIC_DATA, {'value': -15, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -40, 'relative': True}) assert len(calls) == 4 for i in range(0, len(calls)): assert calls[i].data[ATTR_ENTITY_ID] == state.entity_id assert calls[0].data[cover.ATTR_POSITION] == 0 assert calls[1].data[cover.ATTR_POSITION] == 20 assert calls[2].data[cover.ATTR_POSITION] == 15 assert calls[3].data[cover.ATTR_POSITION] == 0
async def test_capability_color_setting_temperature_k_rgb(hass, color_modes): attributes = {light.ATTR_SUPPORTED_COLOR_MODES: color_modes} state = State('light.test', STATE_OFF, attributes) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_TEMPERATURE_K) assert cap.retrievable assert cap.parameters() == { 'color_model': 'rgb', 'temperature_k': { 'max': 4500, 'min': 4500 } } assert cap.get_value() is None cap.state = State( 'light.test', STATE_OFF, dict( { light.ATTR_RGB_COLOR: (0, 0, 0), light.ATTR_COLOR_MODE: color_modes[0] }, **attributes)) assert cap.get_value() is None cap.state = State( 'light.test', STATE_OFF, dict( { light.ATTR_RGB_COLOR: (255, 255, 255), light.ATTR_COLOR_MODE: color_modes[0] }, **attributes)) assert cap.get_value() == 4500 calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON) await cap.set_state(BASIC_DATA, {'value': 4500}) await cap.set_state(BASIC_DATA, {'value': 4300}) assert len(calls) == 2 assert calls[0].data == { ATTR_ENTITY_ID: state.entity_id, light.ATTR_RGB_COLOR: (255, 255, 255) } assert calls[1].data == { ATTR_ENTITY_ID: state.entity_id, light.ATTR_RGB_COLOR: (255, 255, 255) }
async def test_capability_range_channel_set_random_with_value(hass, caplog): state = State( 'media_player.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: media_player.SUPPORT_PLAY_MEDIA, ATTR_DEVICE_CLASS: media_player.DEVICE_CLASS_TV, media_player.ATTR_MEDIA_CONTENT_ID: 15, media_player.ATTR_MEDIA_CONTENT_TYPE: media_player.const.MEDIA_TYPE_CHANNEL }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_CHANNEL) assert cap.retrievable assert cap.support_random_access assert cap.parameters() == { 'instance': 'channel', 'random_access': True, 'range': { 'max': 999, 'min': 0, 'precision': 1 }, } assert cap.get_value() == 15 calls_set = async_mock_service(hass, media_player.DOMAIN, media_player.SERVICE_PLAY_MEDIA) await cap.set_state(BASIC_DATA, {'value': 5, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -3, 'relative': True}) await hass.async_block_till_done() assert len(calls_set) == 2 assert calls_set[0].data == { ATTR_ENTITY_ID: state.entity_id, media_player.ATTR_MEDIA_CONTENT_ID: 20, media_player.ATTR_MEDIA_CONTENT_TYPE: media_player.const.MEDIA_TYPE_CHANNEL } assert calls_set[1].data == { ATTR_ENTITY_ID: state.entity_id, media_player.ATTR_MEDIA_CONTENT_ID: 12, media_player.ATTR_MEDIA_CONTENT_TYPE: media_player.const.MEDIA_TYPE_CHANNEL }
async def test_capability_color_setting_temperature_k(hass, attributes, temp_range): state = State('light.test', STATE_OFF) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_TEMPERATURE_K) state = State('light.test', STATE_OFF, attributes) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_TEMPERATURE_K) assert cap.retrievable assert cap.parameters()['temperature_k'] == { 'max': temp_range[0], 'min': temp_range[1] } assert cap.get_value() is None state = State('light.test', STATE_OFF, dict({light.ATTR_COLOR_TEMP: 370}, **attributes)) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_TEMPERATURE_K) assert cap.get_value() == 2702 calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON) await cap.set_state(BASIC_DATA, {'value': 6500}) assert len(calls) == 1 assert calls[0].data == { ATTR_ENTITY_ID: state.entity_id, light.ATTR_KELVIN: 6500 } state = State( 'light.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: 0, light.ATTR_COLOR_MODE: light.COLOR_MODE_UNKNOWN, }) cap.state = state with pytest.raises(SmartHomeError) as e: await cap.set_state(BASIC_DATA, {'value': 6500}) assert e.value.code == const.ERR_NOT_SUPPORTED_IN_CURRENT_MODE
async def test_capability_range_humidity_fan(hass): state = State('fan.test', water_heater.STATE_OFF) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_HUMIDITY) state = State('fan.test', STATE_OFF, { const.ATTR_TARGET_HUMIDITY: 50, ATTR_MODEL: 'zhimi.test.a' }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_HUMIDITY) assert cap.retrievable assert cap.support_random_access assert cap.parameters() == { 'instance': 'humidity', 'random_access': True, 'range': { 'max': 100, 'min': 0, 'precision': 1 }, 'unit': 'unit.percent', } assert cap.get_value() == 50 calls = async_mock_service(hass, const.DOMAIN_XIAOMI_AIRPURIFIER, const.SERVICE_FAN_SET_TARGET_HUMIDITY) await cap.set_state(BASIC_DATA, {'value': 20}) await cap.set_state(BASIC_DATA, {'value': 100}) await cap.set_state(BASIC_DATA, {'value': 50}) await cap.set_state(BASIC_DATA, {'value': 15, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -5, 'relative': True}) assert len(calls) == 5 for i in range(0, len(calls)): assert calls[i].data[ATTR_ENTITY_ID] == state.entity_id assert calls[0].data[humidifier.ATTR_HUMIDITY] == 20 assert calls[1].data[humidifier.ATTR_HUMIDITY] == 100 assert calls[2].data[humidifier.ATTR_HUMIDITY] == 50 assert calls[3].data[humidifier.ATTR_HUMIDITY] == 65 assert calls[4].data[humidifier.ATTR_HUMIDITY] == 45
async def test_capability_oscillation(hass): state = State('fan.test', STATE_ON) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_OSCILLATION) state = State('fan.test', STATE_ON, {ATTR_SUPPORTED_FEATURES: fan.SUPPORT_OSCILLATE}) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_OSCILLATION) assert cap.retrievable assert cap.parameters() == {'instance': TOGGLE_INSTANCE_OSCILLATION} assert cap.get_value() is False state = State('fan.test', STATE_ON, { ATTR_SUPPORTED_FEATURES: fan.SUPPORT_OSCILLATE, fan.ATTR_OSCILLATING: True }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_OSCILLATION) assert cap.get_value() is True state = State( 'fan.test', STATE_ON, { ATTR_SUPPORTED_FEATURES: fan.SUPPORT_OSCILLATE, fan.ATTR_OSCILLATING: False }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_OSCILLATION) assert cap.get_value() is False calls = async_mock_service(hass, fan.DOMAIN, fan.SERVICE_OSCILLATE) await cap.set_state(BASIC_DATA, {'value': True}) await cap.set_state(BASIC_DATA, {'value': False}) assert len(calls) == 2 assert calls[0].data[ATTR_ENTITY_ID] == state.entity_id assert calls[0].data[fan.ATTR_OSCILLATING] is True assert calls[1].data[ATTR_ENTITY_ID] == state.entity_id assert calls[1].data[fan.ATTR_OSCILLATING] is False
async def test_capability_custom_range_random_access(hass): state = State('switch.test', '30', {}) hass.states.async_set(state.entity_id, state.state) cap = CustomRangeCapability( hass, BASIC_CONFIG, state, 'test_range', { const.CONF_ENTITY_CUSTOM_CAPABILITY_STATE_ENTITY_ID: state.entity_id, const.CONF_ENTITY_RANGE: { const.CONF_ENTITY_RANGE_MIN: 10, const.CONF_ENTITY_RANGE_MAX: 50, const.CONF_ENTITY_RANGE_PRECISION: 3, }, const.CONF_ENTITY_CUSTOM_RANGE_SET_VALUE: { CONF_SERVICE: 'test.set_value', ATTR_ENTITY_ID: 'input_number.test', CONF_SERVICE_DATA: { 'value': dynamic_template('value: {{ value|int }}') } }, }) assert cap.supported() assert cap.retrievable assert cap.support_random_access assert cap.get_value() == 30 calls = async_mock_service(hass, 'test', 'set_value') await cap.set_state(BASIC_DATA, {'value': 40}) await cap.set_state(BASIC_DATA, {'value': 100}) await cap.set_state(BASIC_DATA, {'value': 10, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -3, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -50, 'relative': True}) assert len(calls) == 5 for i in range(0, len(calls)): assert calls[i].data[ATTR_ENTITY_ID] == 'input_number.test' assert calls[0].data['value'] == 'value: 40' assert calls[1].data['value'] == 'value: 100' assert calls[2].data['value'] == 'value: 40' assert calls[3].data['value'] == 'value: 27' assert calls[4].data['value'] == 'value: 10'
async def test_capability_custom_range_random_access_no_state(hass): state = State('switch.test', '30', {}) hass.states.async_set(state.entity_id, state.state) cap = CustomRangeCapability( hass, BASIC_CONFIG, state, 'test_range', { const.CONF_ENTITY_RANGE: { const.CONF_ENTITY_RANGE_MIN: 10, const.CONF_ENTITY_RANGE_MAX: 50, const.CONF_ENTITY_RANGE_PRECISION: 3, }, const.CONF_ENTITY_CUSTOM_RANGE_SET_VALUE: { CONF_SERVICE: 'test.set_value', ATTR_ENTITY_ID: 'input_number.test', CONF_SERVICE_DATA: { 'value': dynamic_template('value: {{ value|int }}') } }, }) assert cap.supported() assert cap.retrievable is False assert cap.support_random_access assert cap.get_value() is None calls = async_mock_service(hass, 'test', 'set_value') await cap.set_state(BASIC_DATA, {'value': 40}) await cap.set_state(BASIC_DATA, {'value': 100}) assert len(calls) == 2 for i in range(0, len(calls)): assert calls[i].data[ATTR_ENTITY_ID] == 'input_number.test' assert calls[0].data['value'] == 'value: 40' assert calls[1].data['value'] == 'value: 100' for v in [10, -3, 50]: with pytest.raises(SmartHomeError) as e: await cap.set_state(BASIC_DATA, {'value': v, 'relative': True}) assert e.value.code == const.ERR_NOT_SUPPORTED_IN_CURRENT_MODE
async def test_capability_pause_cover(hass): state = State('cover.test', STATE_ON) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_PAUSE) for s in [ cover.STATE_OPEN, cover.STATE_CLOSED, cover.STATE_CLOSING, cover.STATE_CLOSING ]: state = State('cover.test', s, {ATTR_SUPPORTED_FEATURES: cover.SUPPORT_STOP}) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_TOGGLE, TOGGLE_INSTANCE_PAUSE) assert cap.retrievable assert cap.parameters() == {'instance': TOGGLE_INSTANCE_PAUSE} assert cap.get_value() is False calls = async_mock_service(hass, cover.DOMAIN, cover.SERVICE_STOP_COVER) await cap.set_state(BASIC_DATA, {'value': True}) await cap.set_state(BASIC_DATA, {'value': False}) assert len(calls) == 2 assert calls[0].data == {ATTR_ENTITY_ID: state.entity_id} assert calls[1].data == {ATTR_ENTITY_ID: state.entity_id}
async def test_capability_color_setting_rgb(hass, color_modes, features): state = State('light.test', STATE_OFF) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_RGB) state = State( 'light.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: features, light.ATTR_SUPPORTED_COLOR_MODES: color_modes }) if not color_modes and not features: assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_RGB) return cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_RGB) assert cap.retrievable if light.COLOR_MODE_RGBWW in color_modes or not color_modes: assert cap.parameters() == {'color_model': 'rgb'} else: assert cap.parameters() == { 'color_model': 'rgb', 'temperature_k': { 'max': 4500 if light.COLOR_MODE_RGBW not in color_modes else 6500, 'min': 4500 } } assert not cap.get_value() attributes = { ATTR_SUPPORTED_FEATURES: features, light.ATTR_SUPPORTED_COLOR_MODES: color_modes } if light.COLOR_MODE_HS in color_modes: attributes[light.ATTR_HS_COLOR] = (240, 100) else: attributes[light.ATTR_RGB_COLOR] = (0, 0, 255) state = State('light.test', STATE_OFF, attributes) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_RGB) assert cap.get_value() == 255 state = State( 'light.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: features, light.ATTR_SUPPORTED_COLOR_MODES: color_modes, light.ATTR_RGB_COLOR: (255, 255, 255) }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_RGB) assert cap.get_value() is None calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON) await cap.set_state(BASIC_DATA, {'value': 720711}) assert len(calls) == 1 assert calls[0].data == { ATTR_ENTITY_ID: state.entity_id, light.ATTR_RGB_COLOR: (10, 255, 71) }
async def test_capability_color_setting_scene(hass): state = State('light.test', STATE_OFF) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_SCENE) state = State( 'light.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: light.SUPPORT_EFFECT, light.ATTR_EFFECT_LIST: ['foo', 'bar'] }) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_SCENE) state = State( 'light.test', STATE_OFF, { ATTR_SUPPORTED_FEATURES: light.SUPPORT_EFFECT, light.ATTR_EFFECT_LIST: ['foo', 'bar', 'Alice'], light.ATTR_EFFECT: 'foo', }) config = MockConfig( entity_config={ state.entity_id: { const.CONF_ENTITY_MODE_MAP: { const.COLOR_SETTING_SCENE: { const.COLOR_SCENE_GARLAND: ['foo'] } } } }) cap = get_exact_one_capability(hass, config, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_SCENE) assert cap.parameters() == { 'color_scene': { 'scenes': [{ 'id': 'alice' }, { 'id': 'garland' }] } } assert cap.get_value() == 'garland' attributes = { ATTR_SUPPORTED_FEATURES: light.SUPPORT_EFFECT, light.ATTR_EFFECT_LIST: ['Leasure', 'Rainbow'] } state = State('light.test', STATE_OFF, attributes) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_COLOR_SETTING, COLOR_SETTING_SCENE) assert cap.retrievable assert cap.parameters() == { 'color_scene': { 'scenes': [{ 'id': 'romance' }, { 'id': 'siren' }] } } assert cap.get_value() is None cap.state = State('light.test', STATE_OFF, dict({light.ATTR_EFFECT: 'Rainbow'}, **attributes)) assert cap.get_value() == 'siren' calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON) await cap.set_state(BASIC_DATA, {'value': 'romance'}) await cap.set_state(BASIC_DATA, {'value': 'invalid'}) assert len(calls) == 2 assert calls[0].data == { ATTR_ENTITY_ID: state.entity_id, light.ATTR_EFFECT: 'Leasure' } assert calls[1].data == { ATTR_ENTITY_ID: state.entity_id, light.ATTR_EFFECT: None }
async def test_capability_range_temperature_climate(hass): state = State('climate.test', climate.STATE_OFF) assert_no_capabilities(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_TEMPERATURE) state = State( 'climate.test', climate.STATE_OFF, { ATTR_SUPPORTED_FEATURES: climate.SUPPORT_TARGET_TEMPERATURE, climate.ATTR_MIN_TEMP: 10, climate.ATTR_MAX_TEMP: 25, climate.ATTR_TARGET_TEMP_STEP: 1, }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_TEMPERATURE) assert cap.retrievable assert cap.support_random_access assert cap.parameters() == { 'instance': 'temperature', 'random_access': True, 'range': { 'max': 25, 'min': 10, 'precision': 1 }, 'unit': 'unit.temperature.celsius', } assert not cap.get_value() state = State( 'climate.test', climate.HVAC_MODE_HEAT_COOL, { ATTR_SUPPORTED_FEATURES: climate.SUPPORT_TARGET_TEMPERATURE, climate.ATTR_MIN_TEMP: 12, climate.ATTR_MAX_TEMP: 27, climate.ATTR_TEMPERATURE: 23.5 }) cap = get_exact_one_capability(hass, BASIC_CONFIG, state, CAPABILITIES_RANGE, RANGE_INSTANCE_TEMPERATURE) assert cap.retrievable assert cap.support_random_access assert cap.parameters() == { 'instance': 'temperature', 'random_access': True, 'range': { 'max': 27, 'min': 12, 'precision': 0.5 }, 'unit': 'unit.temperature.celsius', } assert cap.get_value() == 23.5 calls = async_mock_service(hass, climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE) await cap.set_state(BASIC_DATA, {'value': 11}) await cap.set_state(BASIC_DATA, {'value': 15}) await cap.set_state(BASIC_DATA, {'value': 28}) await cap.set_state(BASIC_DATA, {'value': 10, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -3, 'relative': True}) assert len(calls) == 5 for i in range(0, len(calls)): assert calls[i].data[ATTR_ENTITY_ID] == state.entity_id assert calls[0].data[climate.ATTR_TEMPERATURE] == 11 assert calls[1].data[climate.ATTR_TEMPERATURE] == 15 assert calls[2].data[climate.ATTR_TEMPERATURE] == 28 assert calls[3].data[climate.ATTR_TEMPERATURE] == 27 assert calls[4].data[climate.ATTR_TEMPERATURE] == 20.5
async def test_capability_custom_range_relative_override_no_state(hass): state = State('switch.test', STATE_ON, {}) cap = CustomRangeCapability( hass, BASIC_CONFIG, state, 'test_range', { const.CONF_ENTITY_RANGE: { const.CONF_ENTITY_RANGE_MIN: 10, const.CONF_ENTITY_RANGE_MAX: 99, const.CONF_ENTITY_RANGE_PRECISION: 3, }, const.CONF_ENTITY_CUSTOM_RANGE_SET_VALUE: { CONF_SERVICE: 'test.set_value', ATTR_ENTITY_ID: 'input_number.test', CONF_SERVICE_DATA: { 'value': dynamic_template('value: {{ value|int }}') } }, const.CONF_ENTITY_CUSTOM_RANGE_INCREASE_VALUE: { CONF_SERVICE: 'test.increase_value', ATTR_ENTITY_ID: 'input_number.test', CONF_SERVICE_DATA: { 'value': dynamic_template('value: {{ value|int }}') } }, const.CONF_ENTITY_CUSTOM_RANGE_DECREASE_VALUE: { CONF_SERVICE: 'test.decrease_value', ATTR_ENTITY_ID: 'input_number.test', CONF_SERVICE_DATA: { 'value': dynamic_template('value: {{ value|int }}') } }, }) assert cap.supported() assert cap.support_random_access assert cap.retrievable is False assert cap.get_value() is None calls = async_mock_service(hass, 'test', 'set_value') await cap.set_state(BASIC_DATA, {'value': 40}) await cap.set_state(BASIC_DATA, {'value': 100}) assert len(calls) == 2 for i in range(0, len(calls)): assert calls[i].data[ATTR_ENTITY_ID] == 'input_number.test' assert calls[0].data['value'] == 'value: 40' assert calls[1].data['value'] == 'value: 100' calls = async_mock_service(hass, 'test', 'increase_value') await cap.set_state(BASIC_DATA, {'value': 10, 'relative': True}) assert len(calls) == 1 assert calls[0].data == { 'entity_id': 'input_number.test', 'value': 'value: 10' } calls = async_mock_service(hass, 'test', 'decrease_value') await cap.set_state(BASIC_DATA, {'value': -3, 'relative': True}) await cap.set_state(BASIC_DATA, {'value': -50, 'relative': True}) assert len(calls) == 2 assert calls[0].data == { 'entity_id': 'input_number.test', 'value': 'value: -3' } assert calls[1].data == { 'entity_id': 'input_number.test', 'value': 'value: -50' }