Example #1
0
async def test_reset_cancels_retry_setup():
    """Test resetting a bridge while we're waiting to retry setup."""
    hass = Mock()
    entry = Mock()
    entry.data = {'host': '1.2.3.4', 'username': '******'}
    hue_bridge = bridge.HueBridge(hass, entry, False, False)

    with patch.object(bridge, 'get_bridge', side_effect=errors.CannotConnect):
        assert await hue_bridge.async_setup() is False

    mock_call_later = hass.helpers.event.async_call_later

    assert len(mock_call_later.mock_calls) == 1

    assert await hue_bridge.async_reset()

    assert len(mock_call_later.mock_calls) == 2
    assert len(mock_call_later.return_value.mock_calls) == 1
Example #2
0
async def test_reset_unloads_entry_if_setup():
    """Test calling reset while the entry has been setup."""
    hass = Mock()
    entry = Mock()
    entry.data = {"host": "1.2.3.4", "username": "******"}
    hue_bridge = bridge.HueBridge(hass, entry, False, False)

    with patch.object(bridge, "get_bridge", return_value=mock_coro(Mock())):
        assert await hue_bridge.async_setup() is True

    assert len(hass.services.async_register.mock_calls) == 1
    assert len(hass.config_entries.async_forward_entry_setup.mock_calls) == 3

    hass.config_entries.async_forward_entry_unload.return_value = mock_coro(True)
    assert await hue_bridge.async_reset()

    assert len(hass.config_entries.async_forward_entry_unload.mock_calls) == 3
    assert len(hass.services.async_remove.mock_calls) == 1
Example #3
0
async def test_reset_if_entry_had_wrong_auth(hass):
    """Test calling reset when the entry contained wrong auth."""
    entry = Mock()
    entry.data = {"host": "1.2.3.4", "username": "******"}
    entry.options = {
        CONF_ALLOW_HUE_GROUPS: False,
        CONF_ALLOW_UNREACHABLE: False
    }
    hue_bridge = bridge.HueBridge(hass, entry)

    with patch.object(bridge,
                      "authenticate_bridge",
                      side_effect=errors.AuthenticationRequired), patch.object(
                          bridge, "create_config_flow") as mock_create:
        assert await hue_bridge.async_setup() is False

    assert len(mock_create.mock_calls) == 1

    assert await hue_bridge.async_reset()
Example #4
0
async def test_bridge_setup(hass):
    """Test a successful setup."""
    entry = Mock()
    api = Mock(initialize=AsyncMock())
    entry.data = {"host": "1.2.3.4", "username": "******"}
    entry.options = {
        CONF_ALLOW_HUE_GROUPS: False,
        CONF_ALLOW_UNREACHABLE: False
    }
    hue_bridge = bridge.HueBridge(hass, entry)

    with patch("aiohue.Bridge", return_value=api), patch.object(
            hass.config_entries, "async_forward_entry_setup") as mock_forward:
        assert await hue_bridge.async_setup() is True

    assert hue_bridge.api is api
    assert len(mock_forward.mock_calls) == 3
    forward_entries = {c[1][1] for c in mock_forward.mock_calls}
    assert forward_entries == {"light", "binary_sensor", "sensor"}
Example #5
0
async def test_handle_unauthorized(hass):
    """Test handling an unauthorized error on update."""
    entry = Mock(async_setup=AsyncMock())
    entry.data = {"host": "1.2.3.4", "username": "******"}
    hue_bridge = bridge.HueBridge(hass, entry, False, False)

    with patch.object(bridge, "authenticate_bridge",
                      return_value=Mock()), patch("aiohue.Bridge",
                                                  return_value=Mock()):
        assert await hue_bridge.async_setup() is True

    assert hue_bridge.authorized is True

    with patch.object(bridge, "create_config_flow") as mock_create:
        await hue_bridge.handle_unauthorized_error()

    assert hue_bridge.authorized is False
    assert len(mock_create.mock_calls) == 1
    assert mock_create.mock_calls[0][1][1] == "1.2.3.4"
Example #6
0
async def test_hue_activate_scene_transition(hass, mock_api):
    """Test successful hue_activate_scene with transition."""
    config_entry = config_entries.ConfigEntry(
        1,
        hue.DOMAIN,
        "Mock Title",
        {
            "host": "mock-host",
            "username": "******"
        },
        "test",
        config_entries.CONN_CLASS_LOCAL_POLL,
        system_options={},
        options={
            CONF_ALLOW_HUE_GROUPS: True,
            CONF_ALLOW_UNREACHABLE: False
        },
    )
    hue_bridge = bridge.HueBridge(hass, config_entry)

    mock_api.mock_group_responses.append(GROUP_RESPONSE)
    mock_api.mock_scene_responses.append(SCENE_RESPONSE)

    with patch("aiohue.Bridge", return_value=mock_api), patch.object(
            hass.config_entries, "async_forward_entry_setup"):
        assert await hue_bridge.async_setup() is True

    assert hue_bridge.api is mock_api

    call = Mock()
    call.data = {
        "group_name": "Group 1",
        "scene_name": "Cozy dinner",
        "transition": 30
    }
    with patch("aiohue.Bridge", return_value=mock_api):
        assert await hue_bridge.hue_activate_scene(call) is None

    assert len(mock_api.mock_requests) == 3
    assert mock_api.mock_requests[2]["json"]["scene"] == "scene_1"
    assert mock_api.mock_requests[2]["json"]["transitiontime"] == 30
    assert mock_api.mock_requests[2]["path"] == "groups/group_1/action"
Example #7
0
async def test_handle_unauthorized():
    """Test handling an unauthorized error on update."""
    hass = Mock()
    entry = Mock()
    entry.data = {"host": "1.2.3.4", "username": "******"}
    hue_bridge = bridge.HueBridge(hass, entry, False, False)

    with patch.object(bridge, "get_bridge", return_value=mock_coro(Mock())):
        assert await hue_bridge.async_setup() is True

    assert hue_bridge.authorized is True

    await hue_bridge.handle_unauthorized_error()

    assert hue_bridge.authorized is False
    assert len(hass.async_create_task.mock_calls) == 4
    assert len(hass.config_entries.flow.async_init.mock_calls) == 1
    assert hass.config_entries.flow.async_init.mock_calls[0][2]["data"] == {
        "host": "1.2.3.4"
    }
Example #8
0
async def test_bridge_setup_timeout(hass):
    """Test we retry to connect if we cannot connect."""
    entry = Mock()
    entry.data = {
        "host": "1.2.3.4",
        "api_key": "mock-api-key",
        "api_version": 1
    }
    entry.options = {
        CONF_ALLOW_HUE_GROUPS: False,
        CONF_ALLOW_UNREACHABLE: False
    }
    hue_bridge = bridge.HueBridge(hass, entry)

    with patch.object(
            hue_bridge.api,
            "initialize",
            side_effect=client_exceptions.ServerDisconnectedError,
    ), pytest.raises(ConfigEntryNotReady):
        await hue_bridge.async_initialize_bridge()
Example #9
0
async def test_handle_unauthorized(hass):
    """Test handling an unauthorized error on update."""
    entry = Mock(async_setup=AsyncMock())
    entry.data = {"host": "1.2.3.4", "username": "******"}
    entry.options = {
        CONF_ALLOW_HUE_GROUPS: False,
        CONF_ALLOW_UNREACHABLE: False
    }
    hue_bridge = bridge.HueBridge(hass, entry)

    with patch.object(bridge, "authenticate_bridge"), patch("aiohue.Bridge"):
        assert await hue_bridge.async_setup() is True

    assert hue_bridge.authorized is True

    with patch.object(bridge, "create_config_flow") as mock_create:
        await hue_bridge.handle_unauthorized_error()

    assert hue_bridge.authorized is False
    assert len(mock_create.mock_calls) == 1
    assert mock_create.mock_calls[0][1][1] == "1.2.3.4"
Example #10
0
async def test_bridge_setup_invalid_api_key(hass):
    """Test we start config flow if username is no longer whitelisted."""
    entry = Mock()
    entry.data = {
        "host": "1.2.3.4",
        "api_key": "mock-api-key",
        "api_version": 1
    }
    entry.options = {
        CONF_ALLOW_HUE_GROUPS: False,
        CONF_ALLOW_UNREACHABLE: False
    }
    hue_bridge = bridge.HueBridge(hass, entry)

    with patch.object(hue_bridge.api, "initialize",
                      side_effect=Unauthorized), patch.object(
                          hass.config_entries.flow, "async_init") as mock_init:
        assert await hue_bridge.async_initialize_bridge() is False

    assert len(mock_init.mock_calls) == 1
    assert mock_init.mock_calls[0][2]["data"] == {"host": "1.2.3.4"}
Example #11
0
async def test_reset_unloads_entry_if_setup(hass):
    """Test calling reset while the entry has been setup."""
    entry = Mock()
    entry.data = {"host": "1.2.3.4", "username": "******"}
    entry.options = {CONF_ALLOW_HUE_GROUPS: False, CONF_ALLOW_UNREACHABLE: False}
    hue_bridge = bridge.HueBridge(hass, entry)

    with patch.object(bridge, "authenticate_bridge", return_value=Mock()), patch(
        "aiohue.Bridge", return_value=Mock()
    ), patch.object(hass.config_entries, "async_forward_entry_setup") as mock_forward:
        assert await hue_bridge.async_setup() is True

    assert len(hass.services.async_services()) == 0
    assert len(mock_forward.mock_calls) == 3

    with patch.object(
        hass.config_entries, "async_forward_entry_unload", return_value=True
    ) as mock_forward:
        assert await hue_bridge.async_reset()

    assert len(mock_forward.mock_calls) == 3
    assert len(hass.services.async_services()) == 0
Example #12
0
async def test_handle_unauthorized(hass, mock_api_v1):
    """Test handling an unauthorized error on update."""
    config_entry = Mock(async_setup=AsyncMock())
    config_entry.data = {
        "host": "1.2.3.4",
        "api_key": "mock-api-key",
        "api_version": 1
    }
    config_entry.options = {
        CONF_ALLOW_HUE_GROUPS: False,
        CONF_ALLOW_UNREACHABLE: False
    }

    with patch.object(bridge, "HueBridgeV1", return_value=mock_api_v1):
        hue_bridge = bridge.HueBridge(hass, config_entry)
        assert await hue_bridge.async_initialize_bridge() is True

    with patch.object(bridge, "create_config_flow") as mock_create:
        await hue_bridge.handle_unauthorized_error()

    assert hue_bridge.authorized is False
    assert len(mock_create.mock_calls) == 1
    assert mock_create.mock_calls[0][1][1] == "1.2.3.4"
Example #13
0
async def test_reset_unloads_entry_if_setup(hass):
    """Test calling reset while the entry has been setup."""
    entry = Mock()
    entry.data = {"host": "1.2.3.4", "username": "******"}
    hue_bridge = bridge.HueBridge(hass, entry, False, False)

    with patch.object(bridge,
                      "authenticate_bridge",
                      return_value=mock_coro(Mock())), patch(
                          "aiohue.Bridge", return_value=Mock()), patch.object(
                              hass.config_entries,
                              "async_forward_entry_setup") as mock_forward:
        assert await hue_bridge.async_setup() is True

    assert len(hass.services.async_services()) == 1
    assert len(mock_forward.mock_calls) == 3

    with patch.object(hass.config_entries,
                      "async_forward_entry_unload",
                      return_value=mock_coro(True)) as mock_forward:
        assert await hue_bridge.async_reset()

    assert len(mock_forward.mock_calls) == 3
    assert len(hass.services.async_services()) == 0
Example #14
0
async def test_bridge_setup_v2(hass, mock_api_v2):
    """Test a successful setup for V2 bridge."""
    config_entry = Mock()
    config_entry.data = {
        "host": "1.2.3.4",
        "api_key": "mock-api-key",
        "api_version": 2
    }

    with patch.object(bridge, "HueBridgeV2",
                      return_value=mock_api_v2), patch.object(
                          hass.config_entries,
                          "async_forward_entry_setup") as mock_forward:
        hue_bridge = bridge.HueBridge(hass, config_entry)
        assert await hue_bridge.async_initialize_bridge() is True

    assert hue_bridge.api is mock_api_v2
    assert isinstance(hue_bridge.api, HueBridgeV2)
    assert hue_bridge.api_version == 2
    assert len(mock_forward.mock_calls) == 5
    forward_entries = {c[1][1] for c in mock_forward.mock_calls}
    assert forward_entries == {
        "light", "binary_sensor", "sensor", "switch", "scene"
    }
Example #15
0
async def test_event_updates(hass, caplog):
    """Test calling reset while the entry has been setup."""
    events = asyncio.Queue()

    async def iterate_queue():
        while True:
            event = await events.get()
            if event is None:
                return
            yield event

    async def wait_empty_queue():
        count = 0
        while not events.empty() and count < 50:
            await asyncio.sleep(0)
            count += 1

    hue_bridge = bridge.HueBridge(None, None)
    hue_bridge.api = Mock(listen_events=iterate_queue)
    subscription_task = asyncio.create_task(ORIG_SUBSCRIBE_EVENTS(hue_bridge))

    calls = []

    def obj_updated():
        calls.append(True)

    unsub = hue_bridge.listen_updates("lights", "2", obj_updated)

    events.put_nowait(Mock(ITEM_TYPE="lights", id="1"))

    await wait_empty_queue()
    assert len(calls) == 0

    events.put_nowait(Mock(ITEM_TYPE="lights", id="2"))

    await wait_empty_queue()
    assert len(calls) == 1

    unsub()

    events.put_nowait(Mock(ITEM_TYPE="lights", id="2"))

    await wait_empty_queue()
    assert len(calls) == 1

    # Test we can override update listener.
    def obj_updated_false():
        calls.append(False)

    unsub = hue_bridge.listen_updates("lights", "2", obj_updated)
    unsub_false = hue_bridge.listen_updates("lights", "2", obj_updated_false)

    assert "Overwriting update callback" in caplog.text

    events.put_nowait(Mock(ITEM_TYPE="lights", id="2"))

    await wait_empty_queue()
    assert len(calls) == 2
    assert calls[-1] is False

    # Also call multiple times to make sure that works.
    unsub()
    unsub()
    unsub_false()
    unsub_false()

    events.put_nowait(Mock(ITEM_TYPE="lights", id="2"))

    await wait_empty_queue()
    assert len(calls) == 2

    events.put_nowait(None)
    await subscription_task