Ejemplo n.º 1
0
async def test_zone_get_by_id_details(aresponses, authenticated_local_client):
    """Test getting advanced properties on a specific zone by ID."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/zone/1",
            "get",
            aresponses.Response(text=load_fixture("zone_id_response.json"), status=200),
        )
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/zone/1/properties",
            "get",
            aresponses.Response(
                text=load_fixture("zone_id_properties_response.json"), status=200
            ),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, port=TEST_PORT, ssl=False)
            controller = next(iter(client.controllers.values()))

            data = await controller.zones.get(1, details=True)
            assert data["name"] == "Landscaping"
Ejemplo n.º 2
0
async def test_load_local_skip(
    aresponses,
    auth_login_json,
    provision_wifi_json,
    authenticated_local_client,
    event_loop,
):
    """Test skipping the loading of a local client if it's already loaded."""
    authenticated_local_client.add(
        "{0}:{1}".format(TEST_HOST, TEST_PORT),
        "/api/4/auth/login",
        "post",
        aresponses.Response(text=json.dumps(auth_login_json), status=200),
    )
    authenticated_local_client.add(
        "{0}:{1}".format(TEST_HOST, TEST_PORT),
        "/api/4/provision/wifi",
        "get",
        aresponses.Response(text=json.dumps(provision_wifi_json), status=200),
    )

    async with authenticated_local_client:
        async with aiohttp.ClientSession(loop=event_loop) as websession:
            client = Client(websession)
            await client.load_local(TEST_HOST, TEST_PASSWORD, TEST_PORT, True)
            controller = client.controllers[TEST_MAC]

            await client.load_local(TEST_HOST, TEST_PASSWORD, TEST_PORT, True)
            assert len(client.controllers) == 1
            assert client.controllers[TEST_MAC] == controller
Ejemplo n.º 3
0
async def test_load_remote_skip(aresponses, authenticated_remote_client):
    """Test skipping the loading of a remote client if it's already loaded."""
    authenticated_remote_client.add(
        "my.rainmachine.com",
        "/login/auth",
        "post",
        aresponses.Response(
            text=load_fixture("remote_auth_login_1_response.json"), status=200
        ),
    )
    authenticated_remote_client.add(
        "my.rainmachine.com",
        "/devices/get-sprinklers",
        "post",
        aresponses.Response(
            text=load_fixture("remote_sprinklers_response.json"), status=200
        ),
    )

    async with authenticated_remote_client:
        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_remote(TEST_EMAIL, TEST_PASSWORD, True)
            controller = client.controllers[TEST_MAC]

            await client.load_remote(TEST_EMAIL, TEST_PASSWORD, True)
            assert len(client.controllers) == 1
            assert client.controllers[TEST_MAC] == controller
Ejemplo n.º 4
0
async def test_program_start_and_stop(aresponses, authenticated_local_client):
    """Test starting and stopping a program."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/program/1/start",
            "post",
            aresponses.Response(
                text=load_fixture("program_start_stop_response.json"),
                status=200),
        )
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/program/1/stop",
            "post",
            aresponses.Response(
                text=load_fixture("program_start_stop_response.json"),
                status=200),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST,
                                    TEST_PASSWORD,
                                    port=TEST_PORT,
                                    ssl=False)
            controller = next(iter(client.controllers.values()))

            data = await controller.programs.start(1)
            assert data["message"] == "OK"

            data = await controller.programs.stop(1)
            assert data["message"] == "OK"
Ejemplo n.º 5
0
async def test_load_local_skip(aresponses, authenticated_local_client):
    """Test skipping the loading of a local client if it's already loaded."""
    authenticated_local_client.add(
        f"{TEST_HOST}:{TEST_PORT}",
        "/api/4/auth/login",
        "post",
        aresponses.Response(text=load_fixture("auth_login_response.json"), status=200),
    )
    authenticated_local_client.add(
        f"{TEST_HOST}:{TEST_PORT}",
        "/api/4/provision/wifi",
        "get",
        aresponses.Response(
            text=load_fixture("provision_wifi_response.json"), status=200
        ),
    )

    async with authenticated_local_client:
        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, TEST_PORT, True)
            controller = client.controllers[TEST_MAC]

            await client.load_local(TEST_HOST, TEST_PASSWORD, TEST_PORT, True)
            assert len(client.controllers) == 1
            assert client.controllers[TEST_MAC] == controller
Ejemplo n.º 6
0
async def test_zone_get_details(aresponses, authenticated_local_client):
    """Test getting all zones with details."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/zone",
            "get",
            aresponses.Response(text=load_fixture("zone_response.json"), status=200),
        )
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/zone/properties",
            "get",
            aresponses.Response(
                text=load_fixture("zone_properties_response.json"), status=200
            ),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, port=TEST_PORT, ssl=False)
            controller = next(iter(client.controllers.values()))

            zones = await controller.zones.all(details=True)
            assert len(zones) == 2
            assert zones[1]["name"] == "Landscaping"
            assert zones[1]["active"] is True
            assert zones[1]["ETcoef"] == 0.80000000000000004
Ejemplo n.º 7
0
async def test_watering_pause(aresponses, authenticated_local_client):
    """Test pausing and unpausing watering."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/watering/pauseall",
            "post",
            aresponses.Response(
                text=load_fixture("watering_pause_response.json"), status=200),
        )
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/watering/pauseall",
            "post",
            aresponses.Response(
                text=load_fixture("watering_pause_response.json"), status=200),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST,
                                    TEST_PASSWORD,
                                    port=TEST_PORT,
                                    ssl=False)
            controller = next(iter(client.controllers.values()))

            data = await controller.watering.pause_all(30)
            assert data["message"] == "OK"

            data = await controller.watering.unpause_all()
            assert data["message"] == "OK"
Ejemplo n.º 8
0
async def test_program_enable_disable(aresponses, authenticated_local_client):
    """Test enabling a program."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/program/1",
            "post",
            aresponses.Response(
                text=load_fixture("program_post_response.json"), status=200),
        )
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/program/1",
            "post",
            aresponses.Response(
                text=load_fixture("program_post_response.json"), status=200),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST,
                                    TEST_PASSWORD,
                                    port=TEST_PORT,
                                    ssl=False)
            controller = next(iter(client.controllers.values()))

            resp = await controller.programs.enable(1)
            assert resp["message"] == "OK"

            resp = await controller.programs.disable(1)
            assert resp["message"] == "OK"
Ejemplo n.º 9
0
async def async_get_controller(hass, ip_address, password, port, ssl):
    """Auth and fetch the mac address from the controller."""
    websession = aiohttp_client.async_get_clientsession(hass)
    client = Client(session=websession)
    try:
        await client.load_local(ip_address, password, port=port, ssl=ssl)
    except RainMachineError:
        return None
    else:
        return get_client_controller(client)
Ejemplo n.º 10
0
async def test_load_local_failure(aresponses):
    """Test loading a local client and receiving a fail response."""
    aresponses.add(
        f"{TEST_HOST}:{TEST_PORT}",
        "/api/4/auth/login",
        "post",
        aresponses.Response(text=None, status=500),
    )

    with pytest.raises(RequestError):
        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, TEST_PORT, False)
Ejemplo n.º 11
0
async def test_remote_error_unknown(aresponses, event_loop, remote_error_unknown):
    """Test that remote error handling works."""
    aresponses.add(
        "my.rainmachine.com",
        "/login/auth",
        "post",
        aresponses.Response(text=json.dumps(remote_error_unknown), status=200),
    )

    with pytest.raises(RequestError):
        async with aiohttp.ClientSession(loop=event_loop) as websession:
            client = Client(websession)
            await client.load_remote(TEST_EMAIL, TEST_PASSWORD)
Ejemplo n.º 12
0
async def test_load_local_failure(aresponses, unauthenticated_json, event_loop):
    """Test loading a local client and receiving a fail response."""
    aresponses.add(
        "{0}:{1}".format(TEST_HOST, TEST_PORT),
        "/api/4/auth/login",
        "post",
        aresponses.Response(text=json.dumps(unauthenticated_json), status=401),
    )

    with pytest.raises(RequestError):
        async with aiohttp.ClientSession(loop=event_loop) as websession:
            client = Client(websession)
            await client.load_local(TEST_HOST, TEST_PASSWORD, TEST_PORT, False)
Ejemplo n.º 13
0
async def test_load_remote_failure(aresponses, unauthenticated_json, event_loop):
    """Test loading a remote client and receiving a fail response."""
    aresponses.add(
        "my.rainmachine.com",
        "/login/auth",
        "post",
        aresponses.Response(text=json.dumps(unauthenticated_json), status=401),
    )

    with pytest.raises(RequestError):
        async with aiohttp.ClientSession(loop=event_loop) as websession:
            client = Client(websession)
            await client.load_remote(TEST_EMAIL, TEST_PASSWORD)
Ejemplo n.º 14
0
async def test_legacy_login(authenticated_local_client):
    """Test loading a local client through the legacy method."""
    async with authenticated_local_client:
        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, port=TEST_PORT, ssl=False)
            controller = next(iter(client.controllers.values()))

            assert controller._access_token == TEST_ACCESS_TOKEN
            assert controller.api_version == TEST_API_VERSION
            assert controller.hardware_version == TEST_HW_VERSION
            assert controller.mac == TEST_MAC
            assert controller.name == TEST_NAME
            assert controller.software_version == TEST_SW_VERSION
Ejemplo n.º 15
0
async def test_remote_error_unknown(aresponses):
    """Test that remote error handling works."""
    aresponses.add(
        "my.rainmachine.com",
        "/login/auth",
        "post",
        aresponses.Response(
            text=load_fixture("remote_error_unknown_response.json"), status=200
        ),
    )

    with pytest.raises(RequestError):
        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_remote(TEST_EMAIL, TEST_PASSWORD)
Ejemplo n.º 16
0
async def test_load_remote_failure(aresponses):
    """Test loading a remote client and receiving a fail response."""
    aresponses.add(
        "my.rainmachine.com",
        "/login/auth",
        "post",
        aresponses.Response(
            text=load_fixture("unauthenticated_response.json"), status=401
        ),
    )

    with pytest.raises(TokenExpiredError):
        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_remote(TEST_EMAIL, TEST_PASSWORD)
Ejemplo n.º 17
0
async def test_token_expired_explicit_exception(aresponses):
    """Test that the appropriate error is thrown when a token expires explicitly."""
    aresponses.add(
        f"{TEST_HOST}:{TEST_PORT}",
        "/api/4/auth/login",
        "post",
        aresponses.Response(
            text=load_fixture("unauthenticated_response.json"), status=401
        ),
    )

    with pytest.raises(TokenExpiredError):
        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, TEST_PORT, False)
Ejemplo n.º 18
0
async def test_token_expired_implicit_exception(authenticated_local_client):
    """Test that the appropriate error is thrown when a token expires implicitly."""
    async with authenticated_local_client:
        with pytest.raises(TokenExpiredError):
            async with aiohttp.ClientSession() as session:
                client = Client(session=session)
                await client.load_local(
                    TEST_HOST, TEST_PASSWORD, port=TEST_PORT, ssl=False
                )
                controller = next(iter(client.controllers.values()))

                controller._access_token_expiration = datetime.now() - timedelta(
                    hours=1
                )
                await controller._request("get", "random/endpoint")
Ejemplo n.º 19
0
async def test_request_timeout(authenticated_local_client):  # noqa: D202
    """Test whether the client properly raises an error on timeout."""

    async def long_running_login(*args, **kwargs):  # pylint: disable=unused-argument
        """Define a method that takes 0.5 seconds to execute."""
        await asyncio.sleep(0.5)

    with mock.patch.object(aiohttp.ClientResponse, "json", long_running_login):
        async with authenticated_local_client:
            async with aiohttp.ClientSession() as session:
                with pytest.raises(RequestError):
                    client = Client(session=session, request_timeout=0.1)
                    await client.load_local(
                        TEST_HOST, TEST_PASSWORD, port=TEST_PORT, ssl=False
                    )
Ejemplo n.º 20
0
async def test_load_remote(authenticated_remote_client, event_loop):
    """Test loading a remote client."""
    async with authenticated_remote_client:
        async with aiohttp.ClientSession(loop=event_loop) as session:
            client = Client(session=session)
            await client.load_remote(TEST_EMAIL, TEST_PASSWORD)

            assert len(client.controllers) == 1

            controller = client.controllers[TEST_MAC]
            assert controller._access_token == TEST_ACCESS_TOKEN
            assert controller.api_version == TEST_API_VERSION
            assert controller.hardware_version == TEST_HW_VERSION
            assert controller.mac == TEST_MAC
            assert controller.name == TEST_NAME
            assert controller.software_version == TEST_SW_VERSION
Ejemplo n.º 21
0
async def test_load_local(authenticated_local_client):
    """Test loading a local client."""
    async with authenticated_local_client:
        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, TEST_PORT, False)

            assert len(client.controllers) == 1

            controller = client.controllers[TEST_MAC]
            assert controller._access_token == TEST_ACCESS_TOKEN
            assert controller.api_version == TEST_API_VERSION
            assert controller.hardware_version == TEST_HW_VERSION
            assert controller.mac == TEST_MAC
            assert controller.name == TEST_NAME
            assert controller.software_version == TEST_SW_VERSION
Ejemplo n.º 22
0
    async def async_step_user(self, user_input=None):
        """Handle the start of the config flow."""
        if not user_input:
            return self.async_show_form(step_id="user",
                                        data_schema=DATA_SCHEMA,
                                        errors={})

        await self.async_set_unique_id(user_input[CONF_IP_ADDRESS])
        self._abort_if_unique_id_configured()

        websession = aiohttp_client.async_get_clientsession(self.hass)
        client = Client(session=websession)

        try:
            await client.load_local(
                user_input[CONF_IP_ADDRESS],
                user_input[CONF_PASSWORD],
                port=user_input[CONF_PORT],
                ssl=user_input.get(CONF_SSL, True),
            )
        except RainMachineError:
            return self.async_show_form(
                step_id="user",
                data_schema=DATA_SCHEMA,
                errors={CONF_PASSWORD: "******"},
            )

        # Unfortunately, RainMachine doesn't provide a way to refresh the
        # access token without using the IP address and password, so we have to
        # store it:
        return self.async_create_entry(
            title=user_input[CONF_IP_ADDRESS],
            data={
                CONF_IP_ADDRESS:
                user_input[CONF_IP_ADDRESS],
                CONF_PASSWORD:
                user_input[CONF_PASSWORD],
                CONF_PORT:
                user_input[CONF_PORT],
                CONF_SSL:
                user_input.get(CONF_SSL, True),
                CONF_ZONE_RUN_TIME:
                user_input.get(CONF_ZONE_RUN_TIME, DEFAULT_ZONE_RUN),
            },
        )
Ejemplo n.º 23
0
async def test_parsers_current(aresponses, authenticated_local_client):
    """Test getting all current parsers."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/parser",
            "get",
            aresponses.Response(text=load_fixture("parser_response.json"), status=200),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, port=TEST_PORT, ssl=False)
            controller = next(iter(client.controllers.values()))

            data = await controller.parsers.current()
            assert len(data) == 1
            assert data[0]["name"] == "NOAA Parser"
Ejemplo n.º 24
0
async def test_restrictions_raindelay(aresponses, authenticated_local_client):
    """Test getting any rain delay-related restrictions."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/restrictions/raindelay",
            "get",
            aresponses.Response(
                text=load_fixture("restrictions_raindelay_response.json"), status=200
            ),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, port=TEST_PORT, ssl=False)
            controller = next(iter(client.controllers.values()))

            data = await controller.restrictions.raindelay()
            assert data["delayCounter"] == -1
Ejemplo n.º 25
0
async def test_restrictions_global(aresponses, authenticated_local_client):
    """Test getting any global restrictions."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/restrictions/global",
            "get",
            aresponses.Response(
                text=load_fixture("restrictions_global_response.json"), status=200
            ),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, port=TEST_PORT, ssl=False)
            controller = next(iter(client.controllers.values()))

            data = await controller.restrictions.universal()
            assert data["freezeProtectTemp"] == 2
Ejemplo n.º 26
0
async def test_api_versions_no_explicit_session(aresponses, authenticated_local_client):
    """Test no explicit ClientSession."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/apiVer",
            "get",
            aresponses.Response(
                text=load_fixture("api_version_response.json"), status=200
            ),
        )

        client = Client()
        await client.load_local(TEST_HOST, TEST_PASSWORD, port=TEST_PORT, ssl=False)
        controller = next(iter(client.controllers.values()))

        data = await controller.api.versions()
        assert data["apiVer"] == "4.5.0"
        assert data["hwVer"] == 3
        assert data["swVer"] == "4.0.925"
Ejemplo n.º 27
0
async def test_watering_queue(aresponses, authenticated_local_client):
    """Test getting the watering queue."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/watering/queue",
            "get",
            aresponses.Response(
                text=load_fixture("watering_queue_response.json"), status=200),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST,
                                    TEST_PASSWORD,
                                    port=TEST_PORT,
                                    ssl=False)
            controller = next(iter(client.controllers.values()))

            data = await controller.watering.queue()
            assert not data
Ejemplo n.º 28
0
async def test_api_versions(aresponses, authenticated_local_client):
    """Test getting API, hardware, and software versions."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/apiVer",
            "get",
            aresponses.Response(
                text=load_fixture("api_version_response.json"), status=200
            ),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST, TEST_PASSWORD, port=TEST_PORT, ssl=False)
            controller = next(iter(client.controllers.values()))

            data = await controller.api.versions()
            assert data["apiVer"] == "4.5.0"
            assert data["hwVer"] == 3
            assert data["swVer"] == "4.0.925"
Ejemplo n.º 29
0
async def test_program_get_by_id(aresponses, authenticated_local_client):
    """Test getting a program by its ID."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/program/1",
            "get",
            aresponses.Response(text=load_fixture("program_id_response.json"),
                                status=200),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST,
                                    TEST_PASSWORD,
                                    port=TEST_PORT,
                                    ssl=False)
            controller = next(iter(client.controllers.values()))

            data = await controller.programs.get(1)
            assert data["name"] == "Morning"
Ejemplo n.º 30
0
async def test_diagnostics_log(aresponses, authenticated_local_client):
    """Test retrieving the entire diagnostics log."""
    async with authenticated_local_client:
        authenticated_local_client.add(
            f"{TEST_HOST}:{TEST_PORT}",
            "/api/4/diag/log",
            "get",
            aresponses.Response(text=load_fixture("diag_log_response.json"),
                                status=200),
        )

        async with aiohttp.ClientSession() as session:
            client = Client(session=session)
            await client.load_local(TEST_HOST,
                                    TEST_PASSWORD,
                                    port=TEST_PORT,
                                    ssl=False)
            controller = next(iter(client.controllers.values()))

            data = await controller.diagnostics.log()
            assert data == "----"