752 lines
23 KiB
Python
752 lines
23 KiB
Python
"""The tests for the emulated Hue component."""
|
|
import asyncio
|
|
import json
|
|
from ipaddress import ip_address
|
|
from unittest.mock import patch
|
|
|
|
from aiohttp.hdrs import CONTENT_TYPE
|
|
import pytest
|
|
from tests.common import get_test_instance_port
|
|
|
|
from homeassistant import const, setup
|
|
from homeassistant.components import (
|
|
fan,
|
|
http,
|
|
light,
|
|
script,
|
|
emulated_hue,
|
|
media_player,
|
|
cover,
|
|
climate,
|
|
)
|
|
from homeassistant.components.emulated_hue import Config
|
|
from homeassistant.components.emulated_hue.hue_api import (
|
|
HUE_API_STATE_ON,
|
|
HUE_API_STATE_BRI,
|
|
HUE_API_STATE_HUE,
|
|
HUE_API_STATE_SAT,
|
|
HueUsernameView,
|
|
HueOneLightStateView,
|
|
HueAllLightsStateView,
|
|
HueOneLightChangeView,
|
|
HueAllGroupsStateView,
|
|
)
|
|
from homeassistant.const import STATE_ON, STATE_OFF
|
|
|
|
import homeassistant.util.dt as dt_util
|
|
from datetime import timedelta
|
|
from tests.common import async_fire_time_changed
|
|
|
|
HTTP_SERVER_PORT = get_test_instance_port()
|
|
BRIDGE_SERVER_PORT = get_test_instance_port()
|
|
|
|
BRIDGE_URL_BASE = "http://127.0.0.1:{}".format(BRIDGE_SERVER_PORT) + "{}"
|
|
JSON_HEADERS = {CONTENT_TYPE: const.CONTENT_TYPE_JSON}
|
|
|
|
|
|
@pytest.fixture
|
|
def hass_hue(loop, hass):
|
|
"""Set up a Home Assistant instance for these tests."""
|
|
# We need to do this to get access to homeassistant/turn_(on,off)
|
|
loop.run_until_complete(setup.async_setup_component(hass, "homeassistant", {}))
|
|
|
|
loop.run_until_complete(
|
|
setup.async_setup_component(
|
|
hass, http.DOMAIN, {http.DOMAIN: {http.CONF_SERVER_PORT: HTTP_SERVER_PORT}}
|
|
)
|
|
)
|
|
|
|
with patch("homeassistant.components" ".emulated_hue.UPNPResponderThread"):
|
|
loop.run_until_complete(
|
|
setup.async_setup_component(
|
|
hass,
|
|
emulated_hue.DOMAIN,
|
|
{
|
|
emulated_hue.DOMAIN: {
|
|
emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT,
|
|
emulated_hue.CONF_EXPOSE_BY_DEFAULT: True,
|
|
}
|
|
},
|
|
)
|
|
)
|
|
|
|
loop.run_until_complete(
|
|
setup.async_setup_component(
|
|
hass, light.DOMAIN, {"light": [{"platform": "demo"}]}
|
|
)
|
|
)
|
|
|
|
loop.run_until_complete(
|
|
setup.async_setup_component(
|
|
hass,
|
|
script.DOMAIN,
|
|
{
|
|
"script": {
|
|
"set_kitchen_light": {
|
|
"sequence": [
|
|
{
|
|
"service_template": "light.turn_{{ requested_state }}",
|
|
"data_template": {
|
|
"entity_id": "light.kitchen_lights",
|
|
"brightness": "{{ requested_level }}",
|
|
},
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
)
|
|
)
|
|
|
|
loop.run_until_complete(
|
|
setup.async_setup_component(
|
|
hass, climate.DOMAIN, {"climate": [{"platform": "demo"}]}
|
|
)
|
|
)
|
|
|
|
loop.run_until_complete(
|
|
setup.async_setup_component(
|
|
hass, media_player.DOMAIN, {"media_player": [{"platform": "demo"}]}
|
|
)
|
|
)
|
|
|
|
loop.run_until_complete(
|
|
setup.async_setup_component(hass, fan.DOMAIN, {"fan": [{"platform": "demo"}]})
|
|
)
|
|
|
|
loop.run_until_complete(
|
|
setup.async_setup_component(
|
|
hass, cover.DOMAIN, {"cover": [{"platform": "demo"}]}
|
|
)
|
|
)
|
|
|
|
# Kitchen light is explicitly excluded from being exposed
|
|
kitchen_light_entity = hass.states.get("light.kitchen_lights")
|
|
attrs = dict(kitchen_light_entity.attributes)
|
|
attrs[emulated_hue.ATTR_EMULATED_HUE] = False
|
|
hass.states.async_set(
|
|
kitchen_light_entity.entity_id, kitchen_light_entity.state, attributes=attrs
|
|
)
|
|
|
|
# create a lamp without brightness support
|
|
hass.states.async_set("light.no_brightness", "on", {})
|
|
|
|
# Ceiling Fan is explicitly excluded from being exposed
|
|
ceiling_fan_entity = hass.states.get("fan.ceiling_fan")
|
|
attrs = dict(ceiling_fan_entity.attributes)
|
|
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = True
|
|
hass.states.async_set(
|
|
ceiling_fan_entity.entity_id, ceiling_fan_entity.state, attributes=attrs
|
|
)
|
|
|
|
# Expose the script
|
|
script_entity = hass.states.get("script.set_kitchen_light")
|
|
attrs = dict(script_entity.attributes)
|
|
attrs[emulated_hue.ATTR_EMULATED_HUE] = True
|
|
hass.states.async_set(
|
|
script_entity.entity_id, script_entity.state, attributes=attrs
|
|
)
|
|
|
|
# Expose cover
|
|
cover_entity = hass.states.get("cover.living_room_window")
|
|
attrs = dict(cover_entity.attributes)
|
|
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = False
|
|
hass.states.async_set(cover_entity.entity_id, cover_entity.state, attributes=attrs)
|
|
|
|
# Expose Hvac
|
|
hvac_entity = hass.states.get("climate.hvac")
|
|
attrs = dict(hvac_entity.attributes)
|
|
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = False
|
|
hass.states.async_set(hvac_entity.entity_id, hvac_entity.state, attributes=attrs)
|
|
|
|
# Expose HeatPump
|
|
hp_entity = hass.states.get("climate.heatpump")
|
|
attrs = dict(hp_entity.attributes)
|
|
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = False
|
|
hass.states.async_set(hp_entity.entity_id, hp_entity.state, attributes=attrs)
|
|
|
|
return hass
|
|
|
|
|
|
@pytest.fixture
|
|
def hue_client(loop, hass_hue, aiohttp_client):
|
|
"""Create web client for emulated hue api."""
|
|
web_app = hass_hue.http.app
|
|
config = Config(
|
|
None,
|
|
{
|
|
emulated_hue.CONF_TYPE: emulated_hue.TYPE_ALEXA,
|
|
emulated_hue.CONF_ENTITIES: {
|
|
"light.bed_light": {emulated_hue.CONF_ENTITY_HIDDEN: True},
|
|
"cover.living_room_window": {emulated_hue.CONF_ENTITY_HIDDEN: False},
|
|
},
|
|
},
|
|
)
|
|
|
|
HueUsernameView().register(web_app, web_app.router)
|
|
HueAllLightsStateView(config).register(web_app, web_app.router)
|
|
HueOneLightStateView(config).register(web_app, web_app.router)
|
|
HueOneLightChangeView(config).register(web_app, web_app.router)
|
|
HueAllGroupsStateView(config).register(web_app, web_app.router)
|
|
|
|
return loop.run_until_complete(aiohttp_client(web_app))
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_discover_lights(hue_client):
|
|
"""Test the discovery of lights."""
|
|
result = yield from hue_client.get("/api/username/lights")
|
|
|
|
assert result.status == 200
|
|
assert "application/json" in result.headers["content-type"]
|
|
|
|
result_json = yield from result.json()
|
|
|
|
devices = set(val["uniqueid"] for val in result_json.values())
|
|
|
|
# Make sure the lights we added to the config are there
|
|
assert "light.ceiling_lights" in devices
|
|
assert "light.bed_light" not in devices
|
|
assert "script.set_kitchen_light" in devices
|
|
assert "light.kitchen_lights" not in devices
|
|
assert "media_player.living_room" in devices
|
|
assert "media_player.bedroom" in devices
|
|
assert "media_player.walkman" in devices
|
|
assert "media_player.lounge_room" in devices
|
|
assert "fan.living_room_fan" in devices
|
|
assert "fan.ceiling_fan" not in devices
|
|
assert "cover.living_room_window" in devices
|
|
assert "climate.hvac" in devices
|
|
assert "climate.heatpump" in devices
|
|
assert "climate.ecobee" not in devices
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_light_without_brightness_supported(hass_hue, hue_client):
|
|
"""Test that light without brightness is supported."""
|
|
light_without_brightness_json = yield from perform_get_light_state(
|
|
hue_client, "light.no_brightness", 200
|
|
)
|
|
|
|
assert light_without_brightness_json["state"][HUE_API_STATE_ON] is True
|
|
assert light_without_brightness_json["type"] == "On/off light"
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_get_light_state(hass_hue, hue_client):
|
|
"""Test the getting of light state."""
|
|
# Turn office light on and set to 127 brightness, and set light color
|
|
yield from hass_hue.services.async_call(
|
|
light.DOMAIN,
|
|
const.SERVICE_TURN_ON,
|
|
{
|
|
const.ATTR_ENTITY_ID: "light.ceiling_lights",
|
|
light.ATTR_BRIGHTNESS: 127,
|
|
light.ATTR_RGB_COLOR: (1, 2, 7),
|
|
},
|
|
blocking=True,
|
|
)
|
|
|
|
office_json = yield from perform_get_light_state(
|
|
hue_client, "light.ceiling_lights", 200
|
|
)
|
|
|
|
assert office_json["state"][HUE_API_STATE_ON] is True
|
|
assert office_json["state"][HUE_API_STATE_BRI] == 127
|
|
assert office_json["state"][HUE_API_STATE_HUE] == 41869
|
|
assert office_json["state"][HUE_API_STATE_SAT] == 217
|
|
|
|
# Check all lights view
|
|
result = yield from hue_client.get("/api/username/lights")
|
|
|
|
assert result.status == 200
|
|
assert "application/json" in result.headers["content-type"]
|
|
|
|
result_json = yield from result.json()
|
|
|
|
assert "light.ceiling_lights" in result_json
|
|
assert result_json["light.ceiling_lights"]["state"][HUE_API_STATE_BRI] == 127
|
|
|
|
# Turn office light off
|
|
yield from hass_hue.services.async_call(
|
|
light.DOMAIN,
|
|
const.SERVICE_TURN_OFF,
|
|
{const.ATTR_ENTITY_ID: "light.ceiling_lights"},
|
|
blocking=True,
|
|
)
|
|
|
|
office_json = yield from perform_get_light_state(
|
|
hue_client, "light.ceiling_lights", 200
|
|
)
|
|
|
|
assert office_json["state"][HUE_API_STATE_ON] is False
|
|
assert office_json["state"][HUE_API_STATE_BRI] == 0
|
|
assert office_json["state"][HUE_API_STATE_HUE] == 0
|
|
assert office_json["state"][HUE_API_STATE_SAT] == 0
|
|
|
|
# Make sure bedroom light isn't accessible
|
|
yield from perform_get_light_state(hue_client, "light.bed_light", 404)
|
|
|
|
# Make sure kitchen light isn't accessible
|
|
yield from perform_get_light_state(hue_client, "light.kitchen_lights", 404)
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_put_light_state(hass_hue, hue_client):
|
|
"""Test the setting of light states."""
|
|
yield from perform_put_test_on_ceiling_lights(hass_hue, hue_client)
|
|
|
|
# Turn the bedroom light on first
|
|
yield from hass_hue.services.async_call(
|
|
light.DOMAIN,
|
|
const.SERVICE_TURN_ON,
|
|
{const.ATTR_ENTITY_ID: "light.ceiling_lights", light.ATTR_BRIGHTNESS: 153},
|
|
blocking=True,
|
|
)
|
|
|
|
ceiling_lights = hass_hue.states.get("light.ceiling_lights")
|
|
assert ceiling_lights.state == STATE_ON
|
|
assert ceiling_lights.attributes[light.ATTR_BRIGHTNESS] == 153
|
|
|
|
# update light state through api
|
|
yield from perform_put_light_state(
|
|
hass_hue,
|
|
hue_client,
|
|
"light.ceiling_lights",
|
|
True,
|
|
hue=4369,
|
|
saturation=127,
|
|
brightness=123,
|
|
)
|
|
|
|
# go through api to get the state back
|
|
ceiling_json = yield from perform_get_light_state(
|
|
hue_client, "light.ceiling_lights", 200
|
|
)
|
|
assert ceiling_json["state"][HUE_API_STATE_BRI] == 123
|
|
assert ceiling_json["state"][HUE_API_STATE_HUE] == 4369
|
|
assert ceiling_json["state"][HUE_API_STATE_SAT] == 127
|
|
|
|
# Go through the API to turn it off
|
|
ceiling_result = yield from perform_put_light_state(
|
|
hass_hue, hue_client, "light.ceiling_lights", False
|
|
)
|
|
|
|
ceiling_result_json = yield from ceiling_result.json()
|
|
|
|
assert ceiling_result.status == 200
|
|
assert "application/json" in ceiling_result.headers["content-type"]
|
|
|
|
assert len(ceiling_result_json) == 1
|
|
|
|
# Check to make sure the state changed
|
|
ceiling_lights = hass_hue.states.get("light.ceiling_lights")
|
|
assert ceiling_lights.state == STATE_OFF
|
|
ceiling_json = yield from perform_get_light_state(
|
|
hue_client, "light.ceiling_lights", 200
|
|
)
|
|
assert ceiling_json["state"][HUE_API_STATE_BRI] == 0
|
|
assert ceiling_json["state"][HUE_API_STATE_HUE] == 0
|
|
assert ceiling_json["state"][HUE_API_STATE_SAT] == 0
|
|
|
|
# Make sure we can't change the bedroom light state
|
|
bedroom_result = yield from perform_put_light_state(
|
|
hass_hue, hue_client, "light.bed_light", True
|
|
)
|
|
assert bedroom_result.status == 404
|
|
|
|
# Make sure we can't change the kitchen light state
|
|
kitchen_result = yield from perform_put_light_state(
|
|
hass_hue, hue_client, "light.kitchen_light", True
|
|
)
|
|
assert kitchen_result.status == 404
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_put_light_state_script(hass_hue, hue_client):
|
|
"""Test the setting of script variables."""
|
|
# Turn the kitchen light off first
|
|
yield from hass_hue.services.async_call(
|
|
light.DOMAIN,
|
|
const.SERVICE_TURN_OFF,
|
|
{const.ATTR_ENTITY_ID: "light.kitchen_lights"},
|
|
blocking=True,
|
|
)
|
|
|
|
# Emulated hue converts 0-100% to 0-255.
|
|
level = 23
|
|
brightness = round(level * 255 / 100)
|
|
|
|
script_result = yield from perform_put_light_state(
|
|
hass_hue, hue_client, "script.set_kitchen_light", True, brightness
|
|
)
|
|
|
|
script_result_json = yield from script_result.json()
|
|
|
|
assert script_result.status == 200
|
|
assert len(script_result_json) == 2
|
|
|
|
kitchen_light = hass_hue.states.get("light.kitchen_lights")
|
|
assert kitchen_light.state == "on"
|
|
assert kitchen_light.attributes[light.ATTR_BRIGHTNESS] == level
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_put_light_state_climate_set_temperature(hass_hue, hue_client):
|
|
"""Test setting climate temperature."""
|
|
brightness = 19
|
|
temperature = round(brightness / 255 * 100)
|
|
|
|
hvac_result = yield from perform_put_light_state(
|
|
hass_hue, hue_client, "climate.hvac", True, brightness
|
|
)
|
|
|
|
hvac_result_json = yield from hvac_result.json()
|
|
|
|
assert hvac_result.status == 200
|
|
assert len(hvac_result_json) == 2
|
|
|
|
hvac = hass_hue.states.get("climate.hvac")
|
|
assert hvac.state == climate.const.HVAC_MODE_COOL
|
|
assert hvac.attributes[climate.ATTR_TEMPERATURE] == temperature
|
|
|
|
# Make sure we can't change the ecobee temperature since it's not exposed
|
|
ecobee_result = yield from perform_put_light_state(
|
|
hass_hue, hue_client, "climate.ecobee", True
|
|
)
|
|
assert ecobee_result.status == 404
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_put_light_state_media_player(hass_hue, hue_client):
|
|
"""Test turning on media player and setting volume."""
|
|
# Turn the music player off first
|
|
yield from hass_hue.services.async_call(
|
|
media_player.DOMAIN,
|
|
const.SERVICE_TURN_OFF,
|
|
{const.ATTR_ENTITY_ID: "media_player.walkman"},
|
|
blocking=True,
|
|
)
|
|
|
|
# Emulated hue converts 0.0-1.0 to 0-255.
|
|
level = 0.25
|
|
brightness = round(level * 255)
|
|
|
|
mp_result = yield from perform_put_light_state(
|
|
hass_hue, hue_client, "media_player.walkman", True, brightness
|
|
)
|
|
|
|
mp_result_json = yield from mp_result.json()
|
|
|
|
assert mp_result.status == 200
|
|
assert len(mp_result_json) == 2
|
|
|
|
walkman = hass_hue.states.get("media_player.walkman")
|
|
assert walkman.state == "playing"
|
|
assert walkman.attributes[media_player.ATTR_MEDIA_VOLUME_LEVEL] == level
|
|
|
|
|
|
async def test_close_cover(hass_hue, hue_client):
|
|
"""Test opening cover ."""
|
|
COVER_ID = "cover.living_room_window"
|
|
# Turn the office light off first
|
|
await hass_hue.services.async_call(
|
|
cover.DOMAIN,
|
|
const.SERVICE_CLOSE_COVER,
|
|
{const.ATTR_ENTITY_ID: COVER_ID},
|
|
blocking=True,
|
|
)
|
|
|
|
cover_test = hass_hue.states.get(COVER_ID)
|
|
assert cover_test.state == "closing"
|
|
|
|
for _ in range(7):
|
|
future = dt_util.utcnow() + timedelta(seconds=1)
|
|
async_fire_time_changed(hass_hue, future)
|
|
await hass_hue.async_block_till_done()
|
|
|
|
cover_test = hass_hue.states.get(COVER_ID)
|
|
assert cover_test.state == "closed"
|
|
|
|
# Go through the API to turn it on
|
|
cover_result = await perform_put_light_state(
|
|
hass_hue, hue_client, COVER_ID, True, 100
|
|
)
|
|
|
|
assert cover_result.status == 200
|
|
assert "application/json" in cover_result.headers["content-type"]
|
|
|
|
for _ in range(7):
|
|
future = dt_util.utcnow() + timedelta(seconds=1)
|
|
async_fire_time_changed(hass_hue, future)
|
|
await hass_hue.async_block_till_done()
|
|
|
|
cover_result_json = await cover_result.json()
|
|
|
|
assert len(cover_result_json) == 2
|
|
|
|
# Check to make sure the state changed
|
|
cover_test_2 = hass_hue.states.get(COVER_ID)
|
|
assert cover_test_2.state == "open"
|
|
|
|
|
|
async def test_set_position_cover(hass_hue, hue_client):
|
|
"""Test setting postion cover ."""
|
|
COVER_ID = "cover.living_room_window"
|
|
# Turn the office light off first
|
|
await hass_hue.services.async_call(
|
|
cover.DOMAIN,
|
|
const.SERVICE_CLOSE_COVER,
|
|
{const.ATTR_ENTITY_ID: COVER_ID},
|
|
blocking=True,
|
|
)
|
|
|
|
cover_test = hass_hue.states.get(COVER_ID)
|
|
assert cover_test.state == "closing"
|
|
|
|
for _ in range(7):
|
|
future = dt_util.utcnow() + timedelta(seconds=1)
|
|
async_fire_time_changed(hass_hue, future)
|
|
await hass_hue.async_block_till_done()
|
|
|
|
cover_test = hass_hue.states.get(COVER_ID)
|
|
assert cover_test.state == "closed"
|
|
|
|
level = 20
|
|
brightness = round(level / 100 * 255)
|
|
|
|
# Go through the API to open
|
|
cover_result = await perform_put_light_state(
|
|
hass_hue, hue_client, COVER_ID, False, brightness
|
|
)
|
|
|
|
assert cover_result.status == 200
|
|
assert "application/json" in cover_result.headers["content-type"]
|
|
|
|
cover_result_json = await cover_result.json()
|
|
|
|
assert len(cover_result_json) == 2
|
|
assert True, cover_result_json[0]["success"][
|
|
"/lights/cover.living_room_window/state/on"
|
|
]
|
|
assert (
|
|
cover_result_json[1]["success"]["/lights/cover.living_room_window/state/bri"]
|
|
== level
|
|
)
|
|
|
|
for _ in range(100):
|
|
future = dt_util.utcnow() + timedelta(seconds=1)
|
|
async_fire_time_changed(hass_hue, future)
|
|
await hass_hue.async_block_till_done()
|
|
|
|
# Check to make sure the state changed
|
|
cover_test_2 = hass_hue.states.get(COVER_ID)
|
|
assert cover_test_2.state == "open"
|
|
assert cover_test_2.attributes.get("current_position") == level
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_put_light_state_fan(hass_hue, hue_client):
|
|
"""Test turning on fan and setting speed."""
|
|
# Turn the fan off first
|
|
yield from hass_hue.services.async_call(
|
|
fan.DOMAIN,
|
|
const.SERVICE_TURN_OFF,
|
|
{const.ATTR_ENTITY_ID: "fan.living_room_fan"},
|
|
blocking=True,
|
|
)
|
|
|
|
# Emulated hue converts 0-100% to 0-255.
|
|
level = 43
|
|
brightness = round(level * 255 / 100)
|
|
|
|
fan_result = yield from perform_put_light_state(
|
|
hass_hue, hue_client, "fan.living_room_fan", True, brightness
|
|
)
|
|
|
|
fan_result_json = yield from fan_result.json()
|
|
|
|
assert fan_result.status == 200
|
|
assert len(fan_result_json) == 2
|
|
|
|
living_room_fan = hass_hue.states.get("fan.living_room_fan")
|
|
assert living_room_fan.state == "on"
|
|
assert living_room_fan.attributes[fan.ATTR_SPEED] == fan.SPEED_MEDIUM
|
|
|
|
|
|
# pylint: disable=invalid-name
|
|
@asyncio.coroutine
|
|
def test_put_with_form_urlencoded_content_type(hass_hue, hue_client):
|
|
"""Test the form with urlencoded content."""
|
|
# Needed for Alexa
|
|
yield from perform_put_test_on_ceiling_lights(
|
|
hass_hue, hue_client, "application/x-www-form-urlencoded"
|
|
)
|
|
|
|
# Make sure we fail gracefully when we can't parse the data
|
|
data = {"key1": "value1", "key2": "value2"}
|
|
result = yield from hue_client.put(
|
|
"/api/username/lights/light.ceiling_lights/state",
|
|
headers={"content-type": "application/x-www-form-urlencoded"},
|
|
data=data,
|
|
)
|
|
|
|
assert result.status == 400
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_entity_not_found(hue_client):
|
|
"""Test for entity which are not found."""
|
|
result = yield from hue_client.get("/api/username/lights/not.existant_entity")
|
|
|
|
assert result.status == 404
|
|
|
|
result = yield from hue_client.put("/api/username/lights/not.existant_entity/state")
|
|
|
|
assert result.status == 404
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_allowed_methods(hue_client):
|
|
"""Test the allowed methods."""
|
|
result = yield from hue_client.get(
|
|
"/api/username/lights/light.ceiling_lights/state"
|
|
)
|
|
|
|
assert result.status == 405
|
|
|
|
result = yield from hue_client.put("/api/username/lights/light.ceiling_lights")
|
|
|
|
assert result.status == 405
|
|
|
|
result = yield from hue_client.put("/api/username/lights")
|
|
|
|
assert result.status == 405
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_proper_put_state_request(hue_client):
|
|
"""Test the request to set the state."""
|
|
# Test proper on value parsing
|
|
result = yield from hue_client.put(
|
|
"/api/username/lights/{}/state".format("light.ceiling_lights"),
|
|
data=json.dumps({HUE_API_STATE_ON: 1234}),
|
|
)
|
|
|
|
assert result.status == 400
|
|
|
|
# Test proper brightness value parsing
|
|
result = yield from hue_client.put(
|
|
"/api/username/lights/{}/state".format("light.ceiling_lights"),
|
|
data=json.dumps({HUE_API_STATE_ON: True, HUE_API_STATE_BRI: "Hello world!"}),
|
|
)
|
|
|
|
assert result.status == 400
|
|
|
|
|
|
@asyncio.coroutine
|
|
def test_get_empty_groups_state(hue_client):
|
|
"""Test the request to get groups endpoint."""
|
|
# Test proper on value parsing
|
|
result = yield from hue_client.get("/api/username/groups")
|
|
|
|
assert result.status == 200
|
|
|
|
result_json = yield from result.json()
|
|
|
|
assert result_json == {}
|
|
|
|
|
|
# pylint: disable=invalid-name
|
|
async def perform_put_test_on_ceiling_lights(
|
|
hass_hue, hue_client, content_type="application/json"
|
|
):
|
|
"""Test the setting of a light."""
|
|
# Turn the office light off first
|
|
await hass_hue.services.async_call(
|
|
light.DOMAIN,
|
|
const.SERVICE_TURN_OFF,
|
|
{const.ATTR_ENTITY_ID: "light.ceiling_lights"},
|
|
blocking=True,
|
|
)
|
|
|
|
ceiling_lights = hass_hue.states.get("light.ceiling_lights")
|
|
assert ceiling_lights.state == STATE_OFF
|
|
|
|
# Go through the API to turn it on
|
|
office_result = await perform_put_light_state(
|
|
hass_hue, hue_client, "light.ceiling_lights", True, 56, content_type
|
|
)
|
|
|
|
assert office_result.status == 200
|
|
assert "application/json" in office_result.headers["content-type"]
|
|
|
|
office_result_json = await office_result.json()
|
|
|
|
assert len(office_result_json) == 2
|
|
|
|
# Check to make sure the state changed
|
|
ceiling_lights = hass_hue.states.get("light.ceiling_lights")
|
|
assert ceiling_lights.state == STATE_ON
|
|
assert ceiling_lights.attributes[light.ATTR_BRIGHTNESS] == 56
|
|
|
|
|
|
@asyncio.coroutine
|
|
def perform_get_light_state(client, entity_id, expected_status):
|
|
"""Test the getting of a light state."""
|
|
result = yield from client.get("/api/username/lights/{}".format(entity_id))
|
|
|
|
assert result.status == expected_status
|
|
|
|
if expected_status == 200:
|
|
assert "application/json" in result.headers["content-type"]
|
|
|
|
return (yield from result.json())
|
|
|
|
return None
|
|
|
|
|
|
@asyncio.coroutine
|
|
def perform_put_light_state(
|
|
hass_hue,
|
|
client,
|
|
entity_id,
|
|
is_on,
|
|
brightness=None,
|
|
content_type="application/json",
|
|
hue=None,
|
|
saturation=None,
|
|
):
|
|
"""Test the setting of a light state."""
|
|
req_headers = {"Content-Type": content_type}
|
|
|
|
data = {HUE_API_STATE_ON: is_on}
|
|
|
|
if brightness is not None:
|
|
data[HUE_API_STATE_BRI] = brightness
|
|
if hue is not None:
|
|
data[HUE_API_STATE_HUE] = hue
|
|
if saturation is not None:
|
|
data[HUE_API_STATE_SAT] = saturation
|
|
|
|
result = yield from client.put(
|
|
"/api/username/lights/{}/state".format(entity_id),
|
|
headers=req_headers,
|
|
data=json.dumps(data).encode(),
|
|
)
|
|
|
|
# Wait until state change is complete before continuing
|
|
yield from hass_hue.async_block_till_done()
|
|
|
|
return result
|
|
|
|
|
|
async def test_external_ip_blocked(hue_client):
|
|
"""Test external IP blocked."""
|
|
with patch(
|
|
"homeassistant.components.http.real_ip.ip_address",
|
|
return_value=ip_address("45.45.45.45"),
|
|
):
|
|
result = await hue_client.get("/api/username/lights")
|
|
|
|
assert result.status == 400
|