"""Test service for Tibber integration.""" import asyncio import datetime as dt from unittest.mock import MagicMock from freezegun.api import FrozenDateTimeFactory import pytest from homeassistant.components.tibber.const import DOMAIN from homeassistant.components.tibber.services import PRICE_SERVICE_NAME, __get_prices from homeassistant.core import ServiceCall from homeassistant.exceptions import ServiceValidationError STARTTIME = dt.datetime.fromtimestamp(1615766400) def generate_mock_home_data(): """Create mock data from the tibber connection.""" tomorrow = STARTTIME + dt.timedelta(days=1) mock_homes = [ MagicMock( name="first_home", info={ "viewer": { "home": { "currentSubscription": { "priceInfo": { "today": [ { "startsAt": STARTTIME.isoformat(), "total": 0.46914, "level": "VERY_EXPENSIVE", }, { "startsAt": ( STARTTIME + dt.timedelta(hours=1) ).isoformat(), "total": 0.46914, "level": "VERY_EXPENSIVE", }, ], "tomorrow": [ { "startsAt": tomorrow.isoformat(), "total": 0.46914, "level": "VERY_EXPENSIVE", }, { "startsAt": ( tomorrow + dt.timedelta(hours=1) ).isoformat(), "total": 0.46914, "level": "VERY_EXPENSIVE", }, ], } } } } }, ), MagicMock( name="second_home", info={ "viewer": { "home": { "currentSubscription": { "priceInfo": { "today": [ { "startsAt": STARTTIME.isoformat(), "total": 0.46914, "level": "VERY_EXPENSIVE", }, { "startsAt": ( STARTTIME + dt.timedelta(hours=1) ).isoformat(), "total": 0.46914, "level": "VERY_EXPENSIVE", }, ], "tomorrow": [ { "startsAt": tomorrow.isoformat(), "total": 0.46914, "level": "VERY_EXPENSIVE", }, { "startsAt": ( tomorrow + dt.timedelta(hours=1) ).isoformat(), "total": 0.46914, "level": "VERY_EXPENSIVE", }, ], } } } } }, ), ] mock_homes[0].name = "first_home" mock_homes[1].name = "second_home" return mock_homes def create_mock_tibber_connection(): """Create a mock tibber connection.""" tibber_connection = MagicMock() tibber_connection.get_homes.return_value = generate_mock_home_data() return tibber_connection def create_mock_hass(): """Create a mock hass object.""" mock_hass = MagicMock mock_hass.data = {"tibber": create_mock_tibber_connection()} return mock_hass async def test_get_prices( freezer: FrozenDateTimeFactory, ) -> None: """Test __get_prices with mock data.""" freezer.move_to(STARTTIME) tomorrow = STARTTIME + dt.timedelta(days=1) call = ServiceCall( DOMAIN, PRICE_SERVICE_NAME, {"start": STARTTIME.date().isoformat(), "end": tomorrow.date().isoformat()}, ) result = await __get_prices(call, hass=create_mock_hass()) assert result == { "prices": { "first_home": [ { "start_time": STARTTIME, "price": 0.46914, "level": "VERY_EXPENSIVE", }, { "start_time": STARTTIME + dt.timedelta(hours=1), "price": 0.46914, "level": "VERY_EXPENSIVE", }, ], "second_home": [ { "start_time": STARTTIME, "price": 0.46914, "level": "VERY_EXPENSIVE", }, { "start_time": STARTTIME + dt.timedelta(hours=1), "price": 0.46914, "level": "VERY_EXPENSIVE", }, ], } } async def test_get_prices_no_input( freezer: FrozenDateTimeFactory, ) -> None: """Test __get_prices with no input.""" freezer.move_to(STARTTIME) call = ServiceCall(DOMAIN, PRICE_SERVICE_NAME, {}) result = await __get_prices(call, hass=create_mock_hass()) assert result == { "prices": { "first_home": [ { "start_time": STARTTIME, "price": 0.46914, "level": "VERY_EXPENSIVE", }, { "start_time": STARTTIME + dt.timedelta(hours=1), "price": 0.46914, "level": "VERY_EXPENSIVE", }, ], "second_home": [ { "start_time": STARTTIME, "price": 0.46914, "level": "VERY_EXPENSIVE", }, { "start_time": STARTTIME + dt.timedelta(hours=1), "price": 0.46914, "level": "VERY_EXPENSIVE", }, ], } } async def test_get_prices_start_tomorrow( freezer: FrozenDateTimeFactory, ) -> None: """Test __get_prices with start date tomorrow.""" freezer.move_to(STARTTIME) tomorrow = STARTTIME + dt.timedelta(days=1) call = ServiceCall( DOMAIN, PRICE_SERVICE_NAME, {"start": tomorrow.date().isoformat()} ) result = await __get_prices(call, hass=create_mock_hass()) assert result == { "prices": { "first_home": [ { "start_time": tomorrow, "price": 0.46914, "level": "VERY_EXPENSIVE", }, { "start_time": tomorrow + dt.timedelta(hours=1), "price": 0.46914, "level": "VERY_EXPENSIVE", }, ], "second_home": [ { "start_time": tomorrow, "price": 0.46914, "level": "VERY_EXPENSIVE", }, { "start_time": tomorrow + dt.timedelta(hours=1), "price": 0.46914, "level": "VERY_EXPENSIVE", }, ], } } async def test_get_prices_invalid_input() -> None: """Test __get_prices with invalid input.""" call = ServiceCall(DOMAIN, PRICE_SERVICE_NAME, {"start": "test"}) task = asyncio.create_task(__get_prices(call, hass=create_mock_hass())) with pytest.raises(ServiceValidationError) as excinfo: await task assert "Invalid datetime provided." in str(excinfo.value)