async def test_activated_event(opp, mock_litejet): """Test handling an event from LiteJet.""" await async_init_integration(opp) # Light 1 mock_litejet.get_load_level.return_value = 99 mock_litejet.get_load_level.reset_mock() mock_litejet.load_activated_callbacks[ENTITY_LIGHT_NUMBER]() await opp.async_block_till_done() mock_litejet.get_load_level.assert_called_once_with(ENTITY_LIGHT_NUMBER) assert light.is_on(opp, ENTITY_LIGHT) assert not light.is_on(opp, ENTITY_OTHER_LIGHT) assert opp.states.get(ENTITY_LIGHT).state == "on" assert opp.states.get(ENTITY_OTHER_LIGHT).state == "off" assert opp.states.get(ENTITY_LIGHT).attributes.get(ATTR_BRIGHTNESS) == 255 # Light 2 mock_litejet.get_load_level.return_value = 40 mock_litejet.get_load_level.reset_mock() mock_litejet.load_activated_callbacks[ENTITY_OTHER_LIGHT_NUMBER]() await opp.async_block_till_done() mock_litejet.get_load_level.assert_called_once_with(ENTITY_OTHER_LIGHT_NUMBER) assert light.is_on(opp, ENTITY_LIGHT) assert light.is_on(opp, ENTITY_OTHER_LIGHT) assert opp.states.get(ENTITY_LIGHT).state == "on" assert opp.states.get(ENTITY_OTHER_LIGHT).state == "on" assert ( int(opp.states.get(ENTITY_OTHER_LIGHT).attributes.get(ATTR_BRIGHTNESS)) == 103 )
async def test_deactivated_event(opp, mock_litejet): """Test handling an event from LiteJet.""" await async_init_integration(opp) # Initial state is on. mock_litejet.get_load_level.return_value = 99 mock_litejet.load_activated_callbacks[ENTITY_OTHER_LIGHT_NUMBER]() await opp.async_block_till_done() assert light.is_on(opp, ENTITY_OTHER_LIGHT) # Event indicates it is off now. mock_litejet.get_load_level.reset_mock() mock_litejet.get_load_level.return_value = 0 mock_litejet.load_deactivated_callbacks[ENTITY_OTHER_LIGHT_NUMBER]() await opp.async_block_till_done() # (Requesting the level is not strictly needed with a deactivated # event but the implementation happens to do it. This could be # changed to an assert_not_called in the future.) mock_litejet.get_load_level.assert_called_with(ENTITY_OTHER_LIGHT_NUMBER) assert not light.is_on(opp, ENTITY_OTHER_LIGHT) assert not light.is_on(opp, ENTITY_LIGHT) assert opp.states.get(ENTITY_LIGHT).state == "off" assert opp.states.get(ENTITY_OTHER_LIGHT).state == "off"
async def test_turn_off(opp): """Test light turn off method.""" await opp.services.async_call( "light", "turn_on", {"entity_id": ENTITY_LIGHT}, blocking=True ) assert light.is_on(opp, ENTITY_LIGHT) await opp.services.async_call( "light", "turn_off", {"entity_id": ENTITY_LIGHT}, blocking=True ) assert not light.is_on(opp, ENTITY_LIGHT)
async def test_turn_off_without_entity_id(opp): """Test light turn off all lights.""" await opp.services.async_call( "light", "turn_on", {"entity_id": "all"}, blocking=True ) assert light.is_on(opp, ENTITY_LIGHT) await opp.services.async_call( "light", "turn_off", {"entity_id": "all"}, blocking=True ) assert not light.is_on(opp, ENTITY_LIGHT)
async def test_state_attributes(opp): """Test light state attributes.""" await common.async_turn_on(opp, ENTITY_LIGHT, xy_color=(0.4, 0.4), brightness=25) state = opp.states.get(ENTITY_LIGHT) assert light.is_on(opp, ENTITY_LIGHT) assert (0.4, 0.4) == state.attributes.get(light.ATTR_XY_COLOR) assert 25 == state.attributes.get(light.ATTR_BRIGHTNESS) assert (255, 234, 164) == state.attributes.get(light.ATTR_RGB_COLOR) assert "rainbow" == state.attributes.get(light.ATTR_EFFECT) await common.async_turn_on( opp, ENTITY_LIGHT, rgb_color=(251, 253, 255), white_value=254 ) state = opp.states.get(ENTITY_LIGHT) assert 254 == state.attributes.get(light.ATTR_WHITE_VALUE) assert (250, 252, 255) == state.attributes.get(light.ATTR_RGB_COLOR) assert (0.319, 0.326) == state.attributes.get(light.ATTR_XY_COLOR) await common.async_turn_on(opp, ENTITY_LIGHT, color_temp=400, effect="none") state = opp.states.get(ENTITY_LIGHT) assert 400 == state.attributes.get(light.ATTR_COLOR_TEMP) assert 153 == state.attributes.get(light.ATTR_MIN_MIREDS) assert 500 == state.attributes.get(light.ATTR_MAX_MIREDS) assert "none" == state.attributes.get(light.ATTR_EFFECT) await common.async_turn_on(opp, ENTITY_LIGHT, kelvin=3000, brightness_pct=50) state = opp.states.get(ENTITY_LIGHT) assert 333 == state.attributes.get(light.ATTR_COLOR_TEMP) assert 127 == state.attributes.get(light.ATTR_BRIGHTNESS)
async def setup_lights(opp, entities): """Set up the light component.""" assert await async_setup_component(opp, light.DOMAIN, {light.DOMAIN: { "platform": "test" }}) await opp.async_block_till_done() light_1, light_2 = entities light_1.supported_color_modes = ["brightness"] light_2.supported_color_modes = ["brightness"] await turn_off_lights(opp, [light_1.entity_id, light_2.entity_id]) assert not light.is_on(opp, light_1.entity_id) assert not light.is_on(opp, light_2.entity_id) return light_1, light_2
async def async_set_lights_rgb(opp, lights, rgb, transition): """Set color of array of lights.""" for light in lights: if is_on(opp, light): service_data = {ATTR_ENTITY_ID: light} if rgb is not None: service_data[ATTR_RGB_COLOR] = rgb if transition is not None: service_data[ATTR_TRANSITION] = transition await opp.services.async_call(LIGHT_DOMAIN, SERVICE_TURN_ON, service_data)
async def test_config_yaml_alias_anchor(opp, entities, enable_custom_integrations): """Test the usage of YAML aliases and anchors. The following test scene configuration is equivalent to: scene: - name: test entities: light_1: &light_1_state state: 'on' brightness: 100 light_2: *light_1_state When encountering a YAML alias/anchor, the PyYAML parser will use a reference to the original dictionary, instead of creating a copy, so care needs to be taken to not modify the original. """ light_1, light_2 = await setup_lights(opp, entities) entity_state = {"state": "on", "brightness": 100} assert await async_setup_component( opp, scene.DOMAIN, { "scene": [{ "name": "test", "entities": { light_1.entity_id: entity_state, light_2.entity_id: entity_state, }, }] }, ) await opp.async_block_till_done() await activate(opp, "scene.test") assert light.is_on(opp, light_1.entity_id) assert light.is_on(opp, light_2.entity_id) assert light_1.last_call("turn_on")[1].get("brightness") == 100 assert light_2.last_call("turn_on")[1].get("brightness") == 100
async def test_activate_scene(opp, entities, enable_custom_integrations): """Test active scene.""" light_1, light_2 = await setup_lights(opp, entities) assert await async_setup_component( opp, scene.DOMAIN, { "scene": [{ "name": "test", "entities": { light_1.entity_id: "on", light_2.entity_id: { "state": "on", "brightness": 100 }, }, }] }, ) await opp.async_block_till_done() await activate(opp, "scene.test") assert light.is_on(opp, light_1.entity_id) assert light.is_on(opp, light_2.entity_id) assert light_2.last_call("turn_on")[1].get("brightness") == 100 await turn_off_lights(opp, [light_2.entity_id]) calls = async_mock_service(opp, "light", "turn_on") await opp.services.async_call(scene.DOMAIN, "turn_on", { "transition": 42, "entity_id": "scene.test" }) await opp.async_block_till_done() assert len(calls) == 1 assert calls[0].domain == "light" assert calls[0].service == "turn_on" assert calls[0].data.get("transition") == 42
async def async_set_lights_temp(opp, lights, mired, brightness, transition): """Set color of array of lights.""" for light in lights: if is_on(opp, light): service_data = {ATTR_ENTITY_ID: light} if mired is not None: service_data[ATTR_COLOR_TEMP] = int(mired) if brightness is not None: service_data[ATTR_BRIGHTNESS] = brightness if transition is not None: service_data[ATTR_TRANSITION] = transition await opp.services.async_call(LIGHT_DOMAIN, SERVICE_TURN_ON, service_data)
def test_light_profiles(self): """Test light profiles.""" platform = getattr(self.opp.components, "test.light") platform.init() user_light_file = self.opp.config.path(light.LIGHT_PROFILES_FILE) with open(user_light_file, "w") as user_file: user_file.write("id,x,y,brightness\n") user_file.write("test,.4,.6,100\n") user_file.write("test_off,0,0,0\n") assert setup_component(self.opp, light.DOMAIN, {light.DOMAIN: { CONF_PLATFORM: "test" }}) ent1, _, _ = platform.ENTITIES common.turn_on(self.opp, ent1.entity_id, profile="test") self.opp.block_till_done() _, data = ent1.last_call("turn_on") assert light.is_on(self.opp, ent1.entity_id) assert { light.ATTR_HS_COLOR: (71.059, 100), light.ATTR_BRIGHTNESS: 100 } == data common.turn_on(self.opp, ent1.entity_id, profile="test_off") self.opp.block_till_done() _, data = ent1.last_call("turn_off") assert not light.is_on(self.opp, ent1.entity_id) assert {} == data
async def async_set_lights_xy(opp, lights, x_val, y_val, brightness, transition): """Set color of array of lights.""" for light in lights: if is_on(opp, light): service_data = {ATTR_ENTITY_ID: light} if x_val is not None and y_val is not None: service_data[ATTR_XY_COLOR] = [x_val, y_val] if brightness is not None: service_data[ATTR_BRIGHTNESS] = brightness service_data[ATTR_WHITE_VALUE] = brightness if transition is not None: service_data[ATTR_TRANSITION] = transition await opp.services.async_call(LIGHT_DOMAIN, SERVICE_TURN_ON, service_data)
async def test_config_yaml_bool(opp, entities, enable_custom_integrations): """Test parsing of booleans in yaml config.""" light_1, light_2 = await setup_lights(opp, entities) config = ("scene:\n" " - name: test\n" " entities:\n" f" {light_1.entity_id}: on\n" f" {light_2.entity_id}:\n" " state: on\n" " brightness: 100\n") with io.StringIO(config) as file: doc = yaml_loader.yaml.safe_load(file) assert await async_setup_component(opp, scene.DOMAIN, doc) await opp.async_block_till_done() await activate(opp, "scene.test") assert light.is_on(opp, light_1.entity_id) assert light.is_on(opp, light_2.entity_id) assert light_2.last_call("turn_on")[1].get("brightness") == 100
async def test_on_brightness(opp, mock_litejet): """Test turning the light on with brightness.""" await async_init_integration(opp) assert opp.states.get(ENTITY_LIGHT).state == "off" assert opp.states.get(ENTITY_OTHER_LIGHT).state == "off" assert not light.is_on(opp, ENTITY_LIGHT) await opp.services.async_call( light.DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: ENTITY_LIGHT, ATTR_BRIGHTNESS: 102}, blocking=True, ) mock_litejet.activate_load_at.assert_called_with(ENTITY_LIGHT_NUMBER, 39, 0)
async def test_on_off(opp, mock_litejet): """Test turning the light on and off.""" await async_init_integration(opp) assert opp.states.get(ENTITY_LIGHT).state == "off" assert opp.states.get(ENTITY_OTHER_LIGHT).state == "off" assert not light.is_on(opp, ENTITY_LIGHT) await opp.services.async_call( light.DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: ENTITY_LIGHT}, blocking=True, ) mock_litejet.activate_load.assert_called_with(ENTITY_LIGHT_NUMBER) await opp.services.async_call( light.DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: ENTITY_LIGHT}, blocking=True, ) mock_litejet.deactivate_load.assert_called_with(ENTITY_LIGHT_NUMBER)
def test_methods(self): """Test if methods call the services as expected.""" # Test is_on self.opp.states.set("light.test", STATE_ON) assert light.is_on(self.opp, "light.test") self.opp.states.set("light.test", STATE_OFF) assert not light.is_on(self.opp, "light.test") # Test turn_on turn_on_calls = mock_service(self.opp, light.DOMAIN, SERVICE_TURN_ON) common.turn_on( self.opp, entity_id="entity_id_val", transition="transition_val", brightness="brightness_val", rgb_color="rgb_color_val", xy_color="xy_color_val", profile="profile_val", color_name="color_name_val", white_value="white_val", ) self.opp.block_till_done() assert 1 == len(turn_on_calls) call = turn_on_calls[-1] assert light.DOMAIN == call.domain assert SERVICE_TURN_ON == call.service assert "entity_id_val" == call.data.get(ATTR_ENTITY_ID) assert "transition_val" == call.data.get(light.ATTR_TRANSITION) assert "brightness_val" == call.data.get(light.ATTR_BRIGHTNESS) assert "rgb_color_val" == call.data.get(light.ATTR_RGB_COLOR) assert "xy_color_val" == call.data.get(light.ATTR_XY_COLOR) assert "profile_val" == call.data.get(light.ATTR_PROFILE) assert "color_name_val" == call.data.get(light.ATTR_COLOR_NAME) assert "white_val" == call.data.get(light.ATTR_WHITE_VALUE) # Test turn_off turn_off_calls = mock_service(self.opp, light.DOMAIN, SERVICE_TURN_OFF) common.turn_off(self.opp, entity_id="entity_id_val", transition="transition_val") self.opp.block_till_done() assert 1 == len(turn_off_calls) call = turn_off_calls[-1] assert light.DOMAIN == call.domain assert SERVICE_TURN_OFF == call.service assert "entity_id_val" == call.data[ATTR_ENTITY_ID] assert "transition_val" == call.data[light.ATTR_TRANSITION] # Test toggle toggle_calls = mock_service(self.opp, light.DOMAIN, SERVICE_TOGGLE) common.toggle(self.opp, entity_id="entity_id_val", transition="transition_val") self.opp.block_till_done() assert 1 == len(toggle_calls) call = toggle_calls[-1] assert light.DOMAIN == call.domain assert SERVICE_TOGGLE == call.service assert "entity_id_val" == call.data[ATTR_ENTITY_ID] assert "transition_val" == call.data[light.ATTR_TRANSITION]
def test_services(self): """Test the provided services.""" platform = getattr(self.opp.components, "test.light") platform.init() assert setup_component(self.opp, light.DOMAIN, {light.DOMAIN: { CONF_PLATFORM: "test" }}) ent1, ent2, ent3 = platform.ENTITIES # Test init assert light.is_on(self.opp, ent1.entity_id) assert not light.is_on(self.opp, ent2.entity_id) assert not light.is_on(self.opp, ent3.entity_id) # Test basic turn_on, turn_off, toggle services common.turn_off(self.opp, entity_id=ent1.entity_id) common.turn_on(self.opp, entity_id=ent2.entity_id) self.opp.block_till_done() assert not light.is_on(self.opp, ent1.entity_id) assert light.is_on(self.opp, ent2.entity_id) # turn on all lights common.turn_on(self.opp) self.opp.block_till_done() assert light.is_on(self.opp, ent1.entity_id) assert light.is_on(self.opp, ent2.entity_id) assert light.is_on(self.opp, ent3.entity_id) # turn off all lights common.turn_off(self.opp) self.opp.block_till_done() assert not light.is_on(self.opp, ent1.entity_id) assert not light.is_on(self.opp, ent2.entity_id) assert not light.is_on(self.opp, ent3.entity_id) # turn off all lights by setting brightness to 0 common.turn_on(self.opp) self.opp.block_till_done() common.turn_on(self.opp, brightness=0) self.opp.block_till_done() assert not light.is_on(self.opp, ent1.entity_id) assert not light.is_on(self.opp, ent2.entity_id) assert not light.is_on(self.opp, ent3.entity_id) # toggle all lights common.toggle(self.opp) self.opp.block_till_done() assert light.is_on(self.opp, ent1.entity_id) assert light.is_on(self.opp, ent2.entity_id) assert light.is_on(self.opp, ent3.entity_id) # toggle all lights common.toggle(self.opp) self.opp.block_till_done() assert not light.is_on(self.opp, ent1.entity_id) assert not light.is_on(self.opp, ent2.entity_id) assert not light.is_on(self.opp, ent3.entity_id) # Ensure all attributes process correctly common.turn_on(self.opp, ent1.entity_id, transition=10, brightness=20, color_name="blue") common.turn_on(self.opp, ent2.entity_id, rgb_color=(255, 255, 255), white_value=255) common.turn_on(self.opp, ent3.entity_id, xy_color=(0.4, 0.6)) self.opp.block_till_done() _, data = ent1.last_call("turn_on") assert { light.ATTR_TRANSITION: 10, light.ATTR_BRIGHTNESS: 20, light.ATTR_HS_COLOR: (240, 100), } == data _, data = ent2.last_call("turn_on") assert { light.ATTR_HS_COLOR: (0, 0), light.ATTR_WHITE_VALUE: 255 } == data _, data = ent3.last_call("turn_on") assert {light.ATTR_HS_COLOR: (71.059, 100)} == data # Ensure attributes are filtered when light is turned off common.turn_on(self.opp, ent1.entity_id, transition=10, brightness=0, color_name="blue") common.turn_on( self.opp, ent2.entity_id, brightness=0, rgb_color=(255, 255, 255), white_value=0, ) common.turn_on(self.opp, ent3.entity_id, brightness=0, xy_color=(0.4, 0.6)) self.opp.block_till_done() assert not light.is_on(self.opp, ent1.entity_id) assert not light.is_on(self.opp, ent2.entity_id) assert not light.is_on(self.opp, ent3.entity_id) _, data = ent1.last_call("turn_off") assert {light.ATTR_TRANSITION: 10} == data _, data = ent2.last_call("turn_off") assert {} == data _, data = ent3.last_call("turn_off") assert {} == data # One of the light profiles prof_name, prof_h, prof_s, prof_bri = "relax", 35.932, 69.412, 144 # Test light profiles common.turn_on(self.opp, ent1.entity_id, profile=prof_name) # Specify a profile and a brightness attribute to overwrite it common.turn_on(self.opp, ent2.entity_id, profile=prof_name, brightness=100) self.opp.block_till_done() _, data = ent1.last_call("turn_on") assert { light.ATTR_BRIGHTNESS: prof_bri, light.ATTR_HS_COLOR: (prof_h, prof_s), } == data _, data = ent2.last_call("turn_on") assert { light.ATTR_BRIGHTNESS: 100, light.ATTR_HS_COLOR: (prof_h, prof_s), } == data # Test bad data common.turn_on(self.opp) common.turn_on(self.opp, ent1.entity_id, profile="nonexisting") common.turn_on(self.opp, ent2.entity_id, xy_color=["bla-di-bla", 5]) common.turn_on(self.opp, ent3.entity_id, rgb_color=[255, None, 2]) self.opp.block_till_done() _, data = ent1.last_call("turn_on") assert {} == data _, data = ent2.last_call("turn_on") assert {} == data _, data = ent3.last_call("turn_on") assert {} == data # faulty attributes will not trigger a service call common.turn_on(self.opp, ent1.entity_id, profile=prof_name, brightness="bright") common.turn_on(self.opp, ent1.entity_id, rgb_color="yellowish") common.turn_on(self.opp, ent2.entity_id, white_value="high") self.opp.block_till_done() _, data = ent1.last_call("turn_on") assert {} == data _, data = ent2.last_call("turn_on") assert {} == data
async def test_lights_turn_on_when_coming_home_after_sun_set_person( opp, scanner): """Test lights turn on when coming home after sun set.""" device_1 = f"{DOMAIN}.device_1" device_2 = f"{DOMAIN}.device_2" test_time = datetime(2017, 4, 5, 3, 2, 3, tzinfo=dt_util.UTC) with patch("openpeerpower.util.dt.utcnow", return_value=test_time): await opp.services.async_call(light.DOMAIN, light.SERVICE_TURN_OFF, {ATTR_ENTITY_ID: "all"}, blocking=True) opp.states.async_set(device_1, STATE_NOT_HOME) opp.states.async_set(device_2, STATE_NOT_HOME) await opp.async_block_till_done() assert all(not light.is_on(opp, ent_id) for ent_id in opp.states.async_entity_ids("light")) assert opp.states.get(device_1).state == "not_home" assert opp.states.get(device_2).state == "not_home" assert await async_setup_component( opp, "person", { "person": [{ "id": "me", "name": "Me", "device_trackers": [device_1] }] }, ) assert await async_setup_component(opp, "group", {}) await opp.async_block_till_done() await group.Group.async_create_group(opp, "person_me", ["person.me"]) assert await async_setup_component( opp, device_sun_light_trigger.DOMAIN, { device_sun_light_trigger.DOMAIN: { "device_group": "group.person_me" } }, ) assert all( opp.states.get(ent_id).state == STATE_OFF for ent_id in opp.states.async_entity_ids("light")) assert opp.states.get(device_1).state == "not_home" assert opp.states.get(device_2).state == "not_home" assert opp.states.get("person.me").state == "not_home" # Unrelated device has no impact opp.states.async_set(device_2, STATE_HOME) await opp.async_block_till_done() assert all( opp.states.get(ent_id).state == STATE_OFF for ent_id in opp.states.async_entity_ids("light")) assert opp.states.get(device_1).state == "not_home" assert opp.states.get(device_2).state == "home" assert opp.states.get("person.me").state == "not_home" # person home switches on opp.states.async_set(device_1, STATE_HOME) await opp.async_block_till_done() await opp.async_block_till_done() assert all( opp.states.get(ent_id).state == light.STATE_ON for ent_id in opp.states.async_entity_ids("light")) assert opp.states.get(device_1).state == "home" assert opp.states.get(device_2).state == "home" assert opp.states.get("person.me").state == "home"