|
|
@@ -37,8 +37,22 @@ _EMPTY_DEFAULTS = {
|
|
|
_EMPTY_LOCKS = {CONF_ZWAVE_LOCKS: [], CONF_ZWAVE_SLOT: 1}
|
|
|
|
|
|
|
|
|
-async def _submit_locks_step(hass: HomeAssistant, flow_id: str, user_input: dict | None = None):
|
|
|
- """Submit the locks step (last step in options flow) and return the result."""
|
|
|
+async def _options_init(hass: HomeAssistant, mock_entry):
|
|
|
+ """Start an options flow; returns the init-step result."""
|
|
|
+ mock_entry.add_to_hass(hass)
|
|
|
+ result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
+ assert result["step_id"] == "init"
|
|
|
+ return result
|
|
|
+
|
|
|
+
|
|
|
+async def _select_section(hass: HomeAssistant, flow_id: str, section: str):
|
|
|
+ """Choose a section from the init menu."""
|
|
|
+ return await hass.config_entries.options.async_configure(
|
|
|
+ flow_id, user_input={"section": section}
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+async def _submit_locks(hass: HomeAssistant, flow_id: str, user_input: dict | None = None):
|
|
|
return await hass.config_entries.options.async_configure(
|
|
|
flow_id, user_input=user_input if user_input is not None else _EMPTY_LOCKS
|
|
|
)
|
|
|
@@ -70,37 +84,56 @@ async def test_user_step_creates_entry_with_room_name(hass: HomeAssistant):
|
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-# Options flow — sync_mode step
|
|
|
+# Options flow — init (menu) step
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
-async def test_options_sync_mode_manual(hass: HomeAssistant, mock_entry):
|
|
|
- mock_entry.add_to_hass(hass)
|
|
|
- result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
+async def test_options_init_shows_form(hass: HomeAssistant, mock_entry):
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ assert result["type"] == "form"
|
|
|
+ assert result["step_id"] == "init"
|
|
|
+
|
|
|
+
|
|
|
+async def test_options_init_sync_leads_to_sync_mode(hass: HomeAssistant, mock_entry):
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "sync")
|
|
|
assert result["type"] == "form"
|
|
|
assert result["step_id"] == "sync_mode"
|
|
|
|
|
|
- result = await hass.config_entries.options.async_configure(
|
|
|
- result["flow_id"],
|
|
|
- user_input={CONF_SYNC_MODE: SYNC_MODE_MANUAL},
|
|
|
- )
|
|
|
+
|
|
|
+async def test_options_init_defaults_leads_to_defaults(hass: HomeAssistant, mock_entry):
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "defaults")
|
|
|
assert result["type"] == "form"
|
|
|
assert result["step_id"] == "defaults"
|
|
|
|
|
|
- result = await hass.config_entries.options.async_configure(
|
|
|
- result["flow_id"],
|
|
|
- user_input=_EMPTY_DEFAULTS,
|
|
|
- )
|
|
|
+
|
|
|
+async def test_options_init_locks_leads_to_locks(hass: HomeAssistant, mock_entry):
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "locks")
|
|
|
assert result["type"] == "form"
|
|
|
assert result["step_id"] == "locks"
|
|
|
|
|
|
- result = await _submit_locks_step(hass, result["flow_id"])
|
|
|
+
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
+# Options flow — sync section
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
+
|
|
|
+async def test_options_sync_mode_manual_saves(hass: HomeAssistant, mock_entry):
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "sync")
|
|
|
+ assert result["step_id"] == "sync_mode"
|
|
|
+
|
|
|
+ result = await hass.config_entries.options.async_configure(
|
|
|
+ result["flow_id"],
|
|
|
+ user_input={CONF_SYNC_MODE: SYNC_MODE_MANUAL},
|
|
|
+ )
|
|
|
assert result["type"] == "create_entry"
|
|
|
assert result["data"][CONF_SYNC_MODE] == SYNC_MODE_MANUAL
|
|
|
|
|
|
|
|
|
async def test_options_sync_mode_caldav_proceeds_to_caldav_step(hass: HomeAssistant, mock_entry):
|
|
|
- mock_entry.add_to_hass(hass)
|
|
|
- result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "sync")
|
|
|
result = await hass.config_entries.options.async_configure(
|
|
|
result["flow_id"],
|
|
|
user_input={CONF_SYNC_MODE: SYNC_MODE_CALDAV},
|
|
|
@@ -110,8 +143,8 @@ async def test_options_sync_mode_caldav_proceeds_to_caldav_step(hass: HomeAssist
|
|
|
|
|
|
|
|
|
async def test_options_sync_mode_api_proceeds_to_api_step(hass: HomeAssistant, mock_entry):
|
|
|
- mock_entry.add_to_hass(hass)
|
|
|
- result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "sync")
|
|
|
result = await hass.config_entries.options.async_configure(
|
|
|
result["flow_id"],
|
|
|
user_input={CONF_SYNC_MODE: SYNC_MODE_API},
|
|
|
@@ -124,12 +157,18 @@ async def test_options_sync_mode_api_proceeds_to_api_step(hass: HomeAssistant, m
|
|
|
# Options flow — CalDAV step
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
-async def test_options_caldav_saves_on_success(hass: HomeAssistant, mock_entry):
|
|
|
- mock_entry.add_to_hass(hass)
|
|
|
- result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
- await hass.config_entries.options.async_configure(
|
|
|
+async def _reach_caldav_step(hass: HomeAssistant, mock_entry):
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "sync")
|
|
|
+ result = await hass.config_entries.options.async_configure(
|
|
|
result["flow_id"], user_input={CONF_SYNC_MODE: SYNC_MODE_CALDAV}
|
|
|
)
|
|
|
+ assert result["step_id"] == "caldav"
|
|
|
+ return result
|
|
|
+
|
|
|
+
|
|
|
+async def test_options_caldav_saves_on_success(hass: HomeAssistant, mock_entry):
|
|
|
+ result = await _reach_caldav_step(hass, mock_entry)
|
|
|
|
|
|
with patch("custom_components.room_cal_ha.config_flow._test_caldav_auth", return_value=None):
|
|
|
result = await hass.config_entries.options.async_configure(
|
|
|
@@ -143,17 +182,6 @@ async def test_options_caldav_saves_on_success(hass: HomeAssistant, mock_entry):
|
|
|
},
|
|
|
)
|
|
|
|
|
|
- assert result["type"] == "form"
|
|
|
- assert result["step_id"] == "defaults"
|
|
|
-
|
|
|
- result = await hass.config_entries.options.async_configure(
|
|
|
- result["flow_id"],
|
|
|
- user_input=_EMPTY_DEFAULTS,
|
|
|
- )
|
|
|
- assert result["type"] == "form"
|
|
|
- assert result["step_id"] == "locks"
|
|
|
-
|
|
|
- result = await _submit_locks_step(hass, result["flow_id"])
|
|
|
assert result["type"] == "create_entry"
|
|
|
assert result["data"][CONF_SYNC_MODE] == SYNC_MODE_CALDAV
|
|
|
assert result["data"][CONF_CALDAV_URL] == "https://cal.example.com"
|
|
|
@@ -161,11 +189,7 @@ async def test_options_caldav_saves_on_success(hass: HomeAssistant, mock_entry):
|
|
|
|
|
|
|
|
|
async def test_options_caldav_bad_credentials_shows_error(hass: HomeAssistant, mock_entry):
|
|
|
- mock_entry.add_to_hass(hass)
|
|
|
- result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
- await hass.config_entries.options.async_configure(
|
|
|
- result["flow_id"], user_input={CONF_SYNC_MODE: SYNC_MODE_CALDAV}
|
|
|
- )
|
|
|
+ result = await _reach_caldav_step(hass, mock_entry)
|
|
|
|
|
|
with patch(
|
|
|
"custom_components.room_cal_ha.config_flow._test_caldav_auth",
|
|
|
@@ -187,11 +211,7 @@ async def test_options_caldav_bad_credentials_shows_error(hass: HomeAssistant, m
|
|
|
|
|
|
|
|
|
async def test_options_caldav_connect_error_shows_error(hass: HomeAssistant, mock_entry):
|
|
|
- mock_entry.add_to_hass(hass)
|
|
|
- result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
- await hass.config_entries.options.async_configure(
|
|
|
- result["flow_id"], user_input={CONF_SYNC_MODE: SYNC_MODE_CALDAV}
|
|
|
- )
|
|
|
+ result = await _reach_caldav_step(hass, mock_entry)
|
|
|
|
|
|
with patch(
|
|
|
"custom_components.room_cal_ha.config_flow._test_caldav_auth",
|
|
|
@@ -216,12 +236,18 @@ async def test_options_caldav_connect_error_shows_error(hass: HomeAssistant, moc
|
|
|
# Options flow — API step
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
-async def test_options_api_saves_on_success(hass: HomeAssistant, mock_entry):
|
|
|
- mock_entry.add_to_hass(hass)
|
|
|
- result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
- await hass.config_entries.options.async_configure(
|
|
|
+async def _reach_api_step(hass: HomeAssistant, mock_entry):
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "sync")
|
|
|
+ result = await hass.config_entries.options.async_configure(
|
|
|
result["flow_id"], user_input={CONF_SYNC_MODE: SYNC_MODE_API}
|
|
|
)
|
|
|
+ assert result["step_id"] == "api"
|
|
|
+ return result
|
|
|
+
|
|
|
+
|
|
|
+async def test_options_api_saves_on_success(hass: HomeAssistant, mock_entry):
|
|
|
+ result = await _reach_api_step(hass, mock_entry)
|
|
|
|
|
|
with patch(
|
|
|
"custom_components.room_cal_ha.config_flow._test_api_connection",
|
|
|
@@ -236,17 +262,6 @@ async def test_options_api_saves_on_success(hass: HomeAssistant, mock_entry):
|
|
|
},
|
|
|
)
|
|
|
|
|
|
- assert result["type"] == "form"
|
|
|
- assert result["step_id"] == "defaults"
|
|
|
-
|
|
|
- result = await hass.config_entries.options.async_configure(
|
|
|
- result["flow_id"],
|
|
|
- user_input=_EMPTY_DEFAULTS,
|
|
|
- )
|
|
|
- assert result["type"] == "form"
|
|
|
- assert result["step_id"] == "locks"
|
|
|
-
|
|
|
- result = await _submit_locks_step(hass, result["flow_id"])
|
|
|
assert result["type"] == "create_entry"
|
|
|
assert result["data"][CONF_SYNC_MODE] == SYNC_MODE_API
|
|
|
assert result["data"][CONF_API_BASE_URL] == "https://api.example.com"
|
|
|
@@ -256,11 +271,7 @@ async def test_options_api_saves_on_success(hass: HomeAssistant, mock_entry):
|
|
|
async def test_options_api_bad_token_shows_error(hass: HomeAssistant, mock_entry):
|
|
|
from custom_components.room_cal_ha.config_flow import _ApiAuthError
|
|
|
|
|
|
- mock_entry.add_to_hass(hass)
|
|
|
- result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
- await hass.config_entries.options.async_configure(
|
|
|
- result["flow_id"], user_input={CONF_SYNC_MODE: SYNC_MODE_API}
|
|
|
- )
|
|
|
+ result = await _reach_api_step(hass, mock_entry)
|
|
|
|
|
|
with patch(
|
|
|
"custom_components.room_cal_ha.config_flow._test_api_connection",
|
|
|
@@ -280,11 +291,7 @@ async def test_options_api_bad_token_shows_error(hass: HomeAssistant, mock_entry
|
|
|
|
|
|
|
|
|
async def test_options_api_connect_error_shows_error(hass: HomeAssistant, mock_entry):
|
|
|
- mock_entry.add_to_hass(hass)
|
|
|
- result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
- await hass.config_entries.options.async_configure(
|
|
|
- result["flow_id"], user_input={CONF_SYNC_MODE: SYNC_MODE_API}
|
|
|
- )
|
|
|
+ result = await _reach_api_step(hass, mock_entry)
|
|
|
|
|
|
with patch(
|
|
|
"custom_components.room_cal_ha.config_flow._test_api_connection",
|
|
|
@@ -308,26 +315,12 @@ async def test_options_api_connect_error_shows_error(hass: HomeAssistant, mock_e
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
async def _reach_defaults_step(hass: HomeAssistant, mock_entry):
|
|
|
- """Navigate to the defaults step via manual sync mode."""
|
|
|
- mock_entry.add_to_hass(hass)
|
|
|
- result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
- result = await hass.config_entries.options.async_configure(
|
|
|
- result["flow_id"], user_input={CONF_SYNC_MODE: SYNC_MODE_MANUAL}
|
|
|
- )
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "defaults")
|
|
|
assert result["step_id"] == "defaults"
|
|
|
return result
|
|
|
|
|
|
|
|
|
-async def _reach_locks_step(hass: HomeAssistant, mock_entry):
|
|
|
- """Navigate to the locks step via manual sync mode + empty defaults."""
|
|
|
- result = await _reach_defaults_step(hass, mock_entry)
|
|
|
- result = await hass.config_entries.options.async_configure(
|
|
|
- result["flow_id"], user_input=_EMPTY_DEFAULTS
|
|
|
- )
|
|
|
- assert result["step_id"] == "locks"
|
|
|
- return result
|
|
|
-
|
|
|
-
|
|
|
async def test_options_defaults_saves_values(hass: HomeAssistant, mock_entry):
|
|
|
result = await _reach_defaults_step(hass, mock_entry)
|
|
|
|
|
|
@@ -342,10 +335,6 @@ async def test_options_defaults_saves_values(hass: HomeAssistant, mock_entry):
|
|
|
"door_code": "1234",
|
|
|
},
|
|
|
)
|
|
|
- assert result["type"] == "form"
|
|
|
- assert result["step_id"] == "locks"
|
|
|
-
|
|
|
- result = await _submit_locks_step(hass, result["flow_id"])
|
|
|
assert result["type"] == "create_entry"
|
|
|
defaults = result["data"][CONF_RESERVATION_DEFAULTS]
|
|
|
assert defaults["guest_name"] == "Default Guest"
|
|
|
@@ -363,10 +352,6 @@ async def test_options_defaults_empty_strings_become_none(hass: HomeAssistant, m
|
|
|
result["flow_id"],
|
|
|
user_input=_EMPTY_DEFAULTS,
|
|
|
)
|
|
|
- assert result["type"] == "form"
|
|
|
- assert result["step_id"] == "locks"
|
|
|
-
|
|
|
- result = await _submit_locks_step(hass, result["flow_id"])
|
|
|
assert result["type"] == "create_entry"
|
|
|
defaults = result["data"][CONF_RESERVATION_DEFAULTS]
|
|
|
assert defaults["guest_name"] is None
|
|
|
@@ -389,6 +374,13 @@ async def test_options_defaults_invalid_time_shows_error(hass: HomeAssistant, mo
|
|
|
# Options flow — locks step
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
+async def _reach_locks_step(hass: HomeAssistant, mock_entry):
|
|
|
+ result = await _options_init(hass, mock_entry)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "locks")
|
|
|
+ assert result["step_id"] == "locks"
|
|
|
+ return result
|
|
|
+
|
|
|
+
|
|
|
async def test_options_locks_step_shows_form(hass: HomeAssistant, mock_entry):
|
|
|
result = await _reach_locks_step(hass, mock_entry)
|
|
|
assert result["type"] == "form"
|
|
|
@@ -410,6 +402,27 @@ async def test_options_locks_saves_entities_and_slot(hass: HomeAssistant, mock_e
|
|
|
async def test_options_locks_empty_saves_empty_list(hass: HomeAssistant, mock_entry):
|
|
|
result = await _reach_locks_step(hass, mock_entry)
|
|
|
|
|
|
- result = await _submit_locks_step(hass, result["flow_id"])
|
|
|
+ result = await _submit_locks(hass, result["flow_id"])
|
|
|
assert result["type"] == "create_entry"
|
|
|
assert result["data"][CONF_ZWAVE_LOCKS] == []
|
|
|
+
|
|
|
+
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
+# Cross-section preservation
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
+
|
|
|
+async def test_options_editing_defaults_preserves_sync_mode(hass: HomeAssistant, mock_entry):
|
|
|
+ """Editing defaults alone should not wipe a previously configured sync mode."""
|
|
|
+ from homeassistant.config_entries import ConfigEntry
|
|
|
+ existing_options = {CONF_SYNC_MODE: SYNC_MODE_CALDAV, CONF_CALDAV_URL: "https://cal.example.com"}
|
|
|
+ mock_entry.add_to_hass(hass)
|
|
|
+ hass.config_entries.async_update_entry(mock_entry, options=existing_options)
|
|
|
+
|
|
|
+ result = await hass.config_entries.options.async_init(mock_entry.entry_id)
|
|
|
+ result = await _select_section(hass, result["flow_id"], "defaults")
|
|
|
+ result = await hass.config_entries.options.async_configure(
|
|
|
+ result["flow_id"], user_input=_EMPTY_DEFAULTS
|
|
|
+ )
|
|
|
+ assert result["type"] == "create_entry"
|
|
|
+ assert result["data"][CONF_SYNC_MODE] == SYNC_MODE_CALDAV
|
|
|
+ assert result["data"][CONF_CALDAV_URL] == "https://cal.example.com"
|