Why This Matters
This is the user's explicit starter target. UptimeConfigFlow at custom_components/spook/config_flow.py:14-61 is small but does three things no static analyzer can catch: (1) aborts with already_spooked if an entry already exists, (2) writes a magic sentinel hass.data[DOMAIN] = "Boo!" that triggers a real Home Assistant restart in __init__.py:53-55, and (3) routes through a menu step. That sentinel is a string literal cross-coupling two files — exactly the kind of thing a rename will quietly break without a test. Locking the flow's behavior also establishes the canonical flow.async_init / flow.async_configure pattern that #1259 and any future flow tests will copy.
Approach
Add tests/test_config_flow.py. Use hass.config_entries.flow.async_init(DOMAIN, context={"source": SOURCE_USER}) to start the flow, then drive it with async_configure. Cover four paths: (a) initial async_step_user returns a form, (b) submitting the empty form reaches the choice_restart menu, (c) selecting restart_later creates an entry titled "Your homie" with data={}, (d) selecting restart_now creates the entry AND asserts hass.data[DOMAIN] == "Boo!", (e) a second flow with an existing MockConfigEntry aborts with reason already_spooked. Do NOT let the "Boo!" sentinel actually restart HA in the test — either don't call async_setup_entry after the flow, or patch hass.async_stop.
Acceptance Criteria
Risks & Caveats
The "Boo!" sentinel is a string literal — if a future PR renames it, the test must fail loudly. Consider promoting it to a named constant in const.py (e.g. RESTART_REQUESTED_SENTINEL) as part of this PR; otherwise the test just freezes the typo. The restart side-effect lives in __init__.py, not the config flow, so be careful not to accidentally trigger async_setup_entry in the test fixture.
Scores
- Impact: ████████░░ 8/10
- Difficulty: ████░░░░░░ 4/10
- Short-Term ROI: █████████░ 9/10
- Long-Term Value: ████████░░ 8/10
Priority
Immediate
Dependencies
#1257
Why This Matters
This is the user's explicit starter target.
UptimeConfigFlowatcustom_components/spook/config_flow.py:14-61is small but does three things no static analyzer can catch: (1) aborts withalready_spookedif an entry already exists, (2) writes a magic sentinelhass.data[DOMAIN] = "Boo!"that triggers a real Home Assistant restart in__init__.py:53-55, and (3) routes through a menu step. That sentinel is a string literal cross-coupling two files — exactly the kind of thing a rename will quietly break without a test. Locking the flow's behavior also establishes the canonicalflow.async_init/flow.async_configurepattern that #1259 and any future flow tests will copy.Approach
Add
tests/test_config_flow.py. Usehass.config_entries.flow.async_init(DOMAIN, context={"source": SOURCE_USER})to start the flow, then drive it withasync_configure. Cover four paths: (a) initialasync_step_userreturns a form, (b) submitting the empty form reaches thechoice_restartmenu, (c) selectingrestart_latercreates an entry titled"Your homie"withdata={}, (d) selectingrestart_nowcreates the entry AND assertshass.data[DOMAIN] == "Boo!", (e) a second flow with an existingMockConfigEntryaborts with reasonalready_spooked. Do NOT let the"Boo!"sentinel actually restart HA in the test — either don't callasync_setup_entryafter the flow, or patchhass.async_stop.Acceptance Criteria
"Boo!"sentinel value is referenced viaconst.DOMAIN+ a named constant, not as a magic string in the testRisks & Caveats
The
"Boo!"sentinel is a string literal — if a future PR renames it, the test must fail loudly. Consider promoting it to a named constant inconst.py(e.g.RESTART_REQUESTED_SENTINEL) as part of this PR; otherwise the test just freezes the typo. The restart side-effect lives in__init__.py, not the config flow, so be careful not to accidentally triggerasync_setup_entryin the test fixture.Scores
Priority
Immediate
Dependencies
#1257