Allow workday sensor to be configured without a country (#93048)
* Merge branch 'dev' into workday_without_country * ruff * remove province check * Remove not needed test * Mod config flow --------- Co-authored-by: G Johansson <goran.johansson@shiftit.se>pull/100809/head
parent
b19a0fb2e9
commit
49715f300a
|
@ -13,12 +13,13 @@ from .const import CONF_COUNTRY, CONF_PROVINCE, PLATFORMS
|
|||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up Workday from a config entry."""
|
||||
|
||||
country: str = entry.options[CONF_COUNTRY]
|
||||
country: str | None = entry.options.get(CONF_COUNTRY)
|
||||
province: str | None = entry.options.get(CONF_PROVINCE)
|
||||
|
||||
if country and country not in list_supported_countries():
|
||||
raise ConfigEntryError(f"Selected country {country} is not valid")
|
||||
|
||||
if province and province not in list_supported_countries()[country]:
|
||||
if country and province and province not in list_supported_countries()[country]:
|
||||
raise ConfigEntryError(
|
||||
f"Selected province {province} for country {country} is not valid"
|
||||
)
|
||||
|
|
|
@ -121,21 +121,25 @@ async def async_setup_entry(
|
|||
"""Set up the Workday sensor."""
|
||||
add_holidays: list[DateLike] = entry.options[CONF_ADD_HOLIDAYS]
|
||||
remove_holidays: list[str] = entry.options[CONF_REMOVE_HOLIDAYS]
|
||||
country: str = entry.options[CONF_COUNTRY]
|
||||
country: str | None = entry.options.get(CONF_COUNTRY)
|
||||
days_offset: int = int(entry.options[CONF_OFFSET])
|
||||
excludes: list[str] = entry.options[CONF_EXCLUDES]
|
||||
province: str | None = entry.options.get(CONF_PROVINCE)
|
||||
sensor_name: str = entry.options[CONF_NAME]
|
||||
workdays: list[str] = entry.options[CONF_WORKDAYS]
|
||||
|
||||
year: int = (dt_util.now() + timedelta(days=days_offset)).year
|
||||
|
||||
cls: HolidayBase = country_holidays(country, subdiv=province, years=year)
|
||||
obj_holidays: HolidayBase = country_holidays(
|
||||
country,
|
||||
subdiv=province,
|
||||
years=year,
|
||||
language=cls.default_language,
|
||||
)
|
||||
if country:
|
||||
cls: HolidayBase = country_holidays(country, subdiv=province, years=year)
|
||||
obj_holidays: HolidayBase = country_holidays(
|
||||
country,
|
||||
subdiv=province,
|
||||
years=year,
|
||||
language=cls.default_language,
|
||||
)
|
||||
else:
|
||||
obj_holidays = HolidayBase()
|
||||
|
||||
# Add custom holidays
|
||||
try:
|
||||
|
|
|
@ -52,7 +52,7 @@ def add_province_to_schema(
|
|||
) -> vol.Schema:
|
||||
"""Update schema with province from country."""
|
||||
all_countries = list_supported_countries()
|
||||
if not all_countries[country]:
|
||||
if not all_countries.get(country):
|
||||
return schema
|
||||
|
||||
province_list = [NONE_SENTINEL, *all_countries[country]]
|
||||
|
@ -71,19 +71,21 @@ def add_province_to_schema(
|
|||
|
||||
def validate_custom_dates(user_input: dict[str, Any]) -> None:
|
||||
"""Validate custom dates for add/remove holidays."""
|
||||
|
||||
for add_date in user_input[CONF_ADD_HOLIDAYS]:
|
||||
if dt_util.parse_date(add_date) is None:
|
||||
raise AddDatesError("Incorrect date")
|
||||
|
||||
cls: HolidayBase = country_holidays(user_input[CONF_COUNTRY])
|
||||
year: int = dt_util.now().year
|
||||
obj_holidays: HolidayBase = country_holidays(
|
||||
user_input[CONF_COUNTRY],
|
||||
subdiv=user_input.get(CONF_PROVINCE),
|
||||
years=year,
|
||||
language=cls.default_language,
|
||||
)
|
||||
if country := user_input[CONF_COUNTRY]:
|
||||
cls = country_holidays(country)
|
||||
obj_holidays = country_holidays(
|
||||
country=country,
|
||||
subdiv=user_input.get(CONF_PROVINCE),
|
||||
years=year,
|
||||
language=cls.default_language,
|
||||
)
|
||||
else:
|
||||
obj_holidays = HolidayBase(years=year)
|
||||
|
||||
for remove_date in user_input[CONF_REMOVE_HOLIDAYS]:
|
||||
if dt_util.parse_date(remove_date) is None:
|
||||
|
@ -94,10 +96,11 @@ def validate_custom_dates(user_input: dict[str, Any]) -> None:
|
|||
DATA_SCHEMA_SETUP = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_NAME, default=DEFAULT_NAME): TextSelector(),
|
||||
vol.Required(CONF_COUNTRY): SelectSelector(
|
||||
vol.Optional(CONF_COUNTRY, default=NONE_SENTINEL): SelectSelector(
|
||||
SelectSelectorConfig(
|
||||
options=list(list_supported_countries()),
|
||||
options=[NONE_SENTINEL, *list(list_supported_countries())],
|
||||
mode=SelectSelectorMode.DROPDOWN,
|
||||
translation_key=CONF_COUNTRY,
|
||||
)
|
||||
),
|
||||
}
|
||||
|
@ -208,6 +211,9 @@ class WorkdayConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||
errors: dict[str, str] = {}
|
||||
if user_input is not None:
|
||||
combined_input: dict[str, Any] = {**self.data, **user_input}
|
||||
|
||||
if combined_input.get(CONF_COUNTRY, NONE_SENTINEL) == NONE_SENTINEL:
|
||||
combined_input[CONF_COUNTRY] = None
|
||||
if combined_input.get(CONF_PROVINCE, NONE_SENTINEL) == NONE_SENTINEL:
|
||||
combined_input[CONF_PROVINCE] = None
|
||||
|
||||
|
|
|
@ -66,6 +66,11 @@
|
|||
}
|
||||
},
|
||||
"selector": {
|
||||
"country": {
|
||||
"options": {
|
||||
"none": "No country"
|
||||
}
|
||||
},
|
||||
"province": {
|
||||
"options": {
|
||||
"none": "No subdivision"
|
||||
|
|
|
@ -40,6 +40,22 @@ async def init_integration(
|
|||
return config_entry
|
||||
|
||||
|
||||
TEST_CONFIG_NO_COUNTRY = {
|
||||
"name": DEFAULT_NAME,
|
||||
"excludes": DEFAULT_EXCLUDES,
|
||||
"days_offset": DEFAULT_OFFSET,
|
||||
"workdays": DEFAULT_WORKDAYS,
|
||||
"add_holidays": [],
|
||||
"remove_holidays": [],
|
||||
}
|
||||
TEST_CONFIG_NO_COUNTRY_ADD_HOLIDAY = {
|
||||
"name": DEFAULT_NAME,
|
||||
"excludes": DEFAULT_EXCLUDES,
|
||||
"days_offset": DEFAULT_OFFSET,
|
||||
"workdays": DEFAULT_WORKDAYS,
|
||||
"add_holidays": ["2020-02-24"],
|
||||
"remove_holidays": [],
|
||||
}
|
||||
TEST_CONFIG_WITH_PROVINCE = {
|
||||
"name": DEFAULT_NAME,
|
||||
"country": "DE",
|
||||
|
|
|
@ -19,6 +19,8 @@ from . import (
|
|||
TEST_CONFIG_INCORRECT_ADD_REMOVE,
|
||||
TEST_CONFIG_INCORRECT_COUNTRY,
|
||||
TEST_CONFIG_INCORRECT_PROVINCE,
|
||||
TEST_CONFIG_NO_COUNTRY,
|
||||
TEST_CONFIG_NO_COUNTRY_ADD_HOLIDAY,
|
||||
TEST_CONFIG_NO_PROVINCE,
|
||||
TEST_CONFIG_NO_STATE,
|
||||
TEST_CONFIG_REMOVE_HOLIDAY,
|
||||
|
@ -49,6 +51,7 @@ async def test_valid_country_yaml() -> None:
|
|||
@pytest.mark.parametrize(
|
||||
("config", "expected_state"),
|
||||
[
|
||||
(TEST_CONFIG_NO_COUNTRY, "on"),
|
||||
(TEST_CONFIG_WITH_PROVINCE, "off"),
|
||||
(TEST_CONFIG_NO_PROVINCE, "off"),
|
||||
(TEST_CONFIG_WITH_STATE, "on"),
|
||||
|
@ -71,6 +74,7 @@ async def test_setup(
|
|||
await init_integration(hass, config)
|
||||
|
||||
state = hass.states.get("binary_sensor.workday_sensor")
|
||||
assert state is not None
|
||||
assert state.state == expected_state
|
||||
assert state.attributes == {
|
||||
"friendly_name": "Workday Sensor",
|
||||
|
@ -99,6 +103,7 @@ async def test_setup_from_import(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("binary_sensor.workday_sensor")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
assert state.attributes == {
|
||||
"friendly_name": "Workday Sensor",
|
||||
|
@ -110,7 +115,6 @@ async def test_setup_from_import(
|
|||
|
||||
async def test_setup_with_invalid_province_from_yaml(hass: HomeAssistant) -> None:
|
||||
"""Test setup invalid province with import."""
|
||||
|
||||
await async_setup_component(
|
||||
hass,
|
||||
"binary_sensor",
|
||||
|
@ -137,11 +141,20 @@ async def test_setup_with_working_holiday(
|
|||
await init_integration(hass, TEST_CONFIG_INCLUDE_HOLIDAY)
|
||||
|
||||
state = hass.states.get("binary_sensor.workday_sensor")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"config",
|
||||
[
|
||||
TEST_CONFIG_EXAMPLE_2,
|
||||
TEST_CONFIG_NO_COUNTRY_ADD_HOLIDAY,
|
||||
],
|
||||
)
|
||||
async def test_setup_add_holiday(
|
||||
hass: HomeAssistant,
|
||||
config: dict[str, Any],
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test setup from various configs."""
|
||||
|
@ -149,6 +162,20 @@ async def test_setup_add_holiday(
|
|||
await init_integration(hass, TEST_CONFIG_EXAMPLE_2)
|
||||
|
||||
state = hass.states.get("binary_sensor.workday_sensor")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
|
||||
async def test_setup_no_country_weekend(
|
||||
hass: HomeAssistant,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test setup shows weekend as non-workday with no country."""
|
||||
freezer.move_to(datetime(2020, 2, 23, 12, tzinfo=UTC)) # Sunday
|
||||
await init_integration(hass, TEST_CONFIG_NO_COUNTRY)
|
||||
|
||||
state = hass.states.get("binary_sensor.workday_sensor")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
|
||||
|
@ -161,6 +188,7 @@ async def test_setup_remove_holiday(
|
|||
await init_integration(hass, TEST_CONFIG_REMOVE_HOLIDAY)
|
||||
|
||||
state = hass.states.get("binary_sensor.workday_sensor")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
|
||||
|
||||
|
@ -173,6 +201,7 @@ async def test_setup_remove_holiday_named(
|
|||
await init_integration(hass, TEST_CONFIG_REMOVE_NAMED)
|
||||
|
||||
state = hass.states.get("binary_sensor.workday_sensor")
|
||||
assert state is not None
|
||||
assert state.state == "on"
|
||||
|
||||
|
||||
|
@ -185,6 +214,7 @@ async def test_setup_day_after_tomorrow(
|
|||
await init_integration(hass, TEST_CONFIG_DAY_AFTER_TOMORROW)
|
||||
|
||||
state = hass.states.get("binary_sensor.workday_sensor")
|
||||
assert state is not None
|
||||
assert state.state == "off"
|
||||
|
||||
|
||||
|
|
|
@ -72,6 +72,48 @@ async def test_form(hass: HomeAssistant) -> None:
|
|||
}
|
||||
|
||||
|
||||
async def test_form_no_country(hass: HomeAssistant) -> None:
|
||||
"""Test we get the forms correctly without a country."""
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == FlowResultType.FORM
|
||||
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_NAME: "Workday Sensor",
|
||||
CONF_COUNTRY: "none",
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
result3 = await hass.config_entries.flow.async_configure(
|
||||
result2["flow_id"],
|
||||
{
|
||||
CONF_EXCLUDES: DEFAULT_EXCLUDES,
|
||||
CONF_OFFSET: DEFAULT_OFFSET,
|
||||
CONF_WORKDAYS: DEFAULT_WORKDAYS,
|
||||
CONF_ADD_HOLIDAYS: [],
|
||||
CONF_REMOVE_HOLIDAYS: [],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result3["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result3["title"] == "Workday Sensor"
|
||||
assert result3["options"] == {
|
||||
"name": "Workday Sensor",
|
||||
"country": None,
|
||||
"excludes": ["sat", "sun", "holiday"],
|
||||
"days_offset": 0,
|
||||
"workdays": ["mon", "tue", "wed", "thu", "fri"],
|
||||
"add_holidays": [],
|
||||
"remove_holidays": [],
|
||||
"province": None,
|
||||
}
|
||||
|
||||
|
||||
async def test_form_no_subdivision(hass: HomeAssistant) -> None:
|
||||
"""Test we get the forms correctly without subdivision."""
|
||||
|
||||
|
|
Loading…
Reference in New Issue