test_config_flow.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. """Tests for the config flow."""
  2. from unittest.mock import ANY, AsyncMock, MagicMock, patch
  3. import pytest
  4. import voluptuous as vol
  5. from homeassistant.const import CONF_HOST, CONF_NAME
  6. from homeassistant.data_entry_flow import FlowResultType
  7. from pytest_homeassistant_custom_component.common import MockConfigEntry
  8. from custom_components.tuya_local import (
  9. async_migrate_entry,
  10. config_flow,
  11. )
  12. from custom_components.tuya_local.const import (
  13. CONF_DEVICE_CID,
  14. CONF_DEVICE_ID,
  15. CONF_LOCAL_KEY,
  16. CONF_POLL_ONLY,
  17. CONF_PROTOCOL_VERSION,
  18. CONF_TYPE,
  19. DOMAIN,
  20. )
  21. TESTKEY = ")<jO<@)'P1dkR$Kd"
  22. @pytest.fixture(autouse=True)
  23. def auto_enable_custom_integrations(enable_custom_integrations):
  24. yield
  25. @pytest.fixture(autouse=True)
  26. def prevent_task_creation():
  27. with patch(
  28. "custom_components.tuya_local.device.TuyaLocalDevice.register_entity",
  29. ):
  30. yield
  31. @pytest.fixture
  32. def bypass_setup():
  33. """Prevent actual setup of the integration after config flow."""
  34. with patch(
  35. "custom_components.tuya_local.async_setup_entry",
  36. return_value=True,
  37. ):
  38. yield
  39. @pytest.mark.asyncio
  40. async def test_init_entry(hass):
  41. """Test initialisation of the config flow."""
  42. entry = MockConfigEntry(
  43. domain=DOMAIN,
  44. version=11,
  45. title="test",
  46. data={
  47. CONF_DEVICE_ID: "deviceid",
  48. CONF_HOST: "hostname",
  49. CONF_LOCAL_KEY: TESTKEY,
  50. CONF_POLL_ONLY: False,
  51. CONF_PROTOCOL_VERSION: "auto",
  52. CONF_TYPE: "kogan_kahtp_heater",
  53. CONF_DEVICE_CID: None,
  54. },
  55. options={},
  56. )
  57. entry.add_to_hass(hass)
  58. await hass.config_entries.async_setup(entry.entry_id)
  59. await hass.async_block_till_done()
  60. assert hass.states.get("climate.test")
  61. assert hass.states.get("lock.test_child_lock")
  62. @pytest.mark.asyncio
  63. @patch("custom_components.tuya_local.setup_device")
  64. async def test_migrate_entry(mock_setup, hass):
  65. """Test migration from old entry format."""
  66. mock_device = MagicMock()
  67. mock_device.async_inferred_type = AsyncMock(return_value="goldair_gpph_heater")
  68. mock_setup.return_value = mock_device
  69. entry = MockConfigEntry(
  70. domain=DOMAIN,
  71. version=1,
  72. title="test",
  73. data={
  74. CONF_DEVICE_ID: "deviceid",
  75. CONF_HOST: "hostname",
  76. CONF_LOCAL_KEY: TESTKEY,
  77. CONF_TYPE: "auto",
  78. "climate": True,
  79. "child_lock": True,
  80. "display_light": True,
  81. },
  82. )
  83. entry.add_to_hass(hass)
  84. assert await async_migrate_entry(hass, entry)
  85. mock_device.async_inferred_type = AsyncMock(return_value=None)
  86. mock_device.reset_mock()
  87. entry = MockConfigEntry(
  88. domain=DOMAIN,
  89. version=1,
  90. title="test2",
  91. data={
  92. CONF_DEVICE_ID: "deviceid",
  93. CONF_HOST: "hostname",
  94. CONF_LOCAL_KEY: TESTKEY,
  95. CONF_TYPE: "unknown",
  96. "climate": False,
  97. },
  98. )
  99. entry.add_to_hass(hass)
  100. assert not await async_migrate_entry(hass, entry)
  101. mock_device.reset_mock()
  102. entry = MockConfigEntry(
  103. domain=DOMAIN,
  104. version=2,
  105. title="test3",
  106. data={
  107. CONF_DEVICE_ID: "deviceid",
  108. CONF_HOST: "hostname",
  109. CONF_LOCAL_KEY: TESTKEY,
  110. CONF_TYPE: "auto",
  111. },
  112. options={
  113. "climate": False,
  114. },
  115. )
  116. entry.add_to_hass(hass)
  117. assert not await async_migrate_entry(hass, entry)
  118. mock_device.async_inferred_type = AsyncMock(return_value="smartplugv1")
  119. mock_device.reset_mock()
  120. entry = MockConfigEntry(
  121. domain=DOMAIN,
  122. version=3,
  123. title="test4",
  124. data={
  125. CONF_DEVICE_ID: "deviceid",
  126. CONF_HOST: "hostname",
  127. CONF_LOCAL_KEY: TESTKEY,
  128. CONF_TYPE: "smartplugv1",
  129. },
  130. options={
  131. "switch": True,
  132. },
  133. )
  134. entry.add_to_hass(hass)
  135. assert await async_migrate_entry(hass, entry)
  136. mock_device.async_inferred_type = AsyncMock(return_value="smartplugv2")
  137. mock_device.reset_mock()
  138. entry = MockConfigEntry(
  139. domain=DOMAIN,
  140. version=3,
  141. title="test5",
  142. data={
  143. CONF_DEVICE_ID: "deviceid",
  144. CONF_HOST: "hostname",
  145. CONF_LOCAL_KEY: TESTKEY,
  146. CONF_TYPE: "smartplugv1",
  147. },
  148. options={
  149. "switch": True,
  150. },
  151. )
  152. entry.add_to_hass(hass)
  153. assert await async_migrate_entry(hass, entry)
  154. mock_device.async_inferred_type = AsyncMock(return_value="goldair_dehumidifier")
  155. mock_device.reset_mock()
  156. entry = MockConfigEntry(
  157. domain=DOMAIN,
  158. version=4,
  159. title="test6",
  160. data={
  161. CONF_DEVICE_ID: "deviceid",
  162. CONF_HOST: "hostname",
  163. CONF_LOCAL_KEY: TESTKEY,
  164. CONF_TYPE: "goldair_dehumidifier",
  165. },
  166. options={
  167. "humidifier": True,
  168. "fan": True,
  169. "light": True,
  170. "lock": False,
  171. "switch": True,
  172. },
  173. )
  174. entry.add_to_hass(hass)
  175. assert await async_migrate_entry(hass, entry)
  176. mock_device.async_inferred_type = AsyncMock(
  177. return_value="grid_connect_usb_double_power_point"
  178. )
  179. mock_device.reset_mock()
  180. entry = MockConfigEntry(
  181. domain=DOMAIN,
  182. version=6,
  183. title="test7",
  184. data={
  185. CONF_DEVICE_ID: "deviceid",
  186. CONF_HOST: "hostname",
  187. CONF_LOCAL_KEY: TESTKEY,
  188. CONF_TYPE: "grid_connect_usb_double_power_point",
  189. },
  190. options={
  191. "switch_main_switch": True,
  192. "switch_left_outlet": True,
  193. "switch_right_outlet": True,
  194. },
  195. )
  196. entry.add_to_hass(hass)
  197. assert await async_migrate_entry(hass, entry)
  198. @pytest.mark.asyncio
  199. async def test_flow_user_init(hass):
  200. """Test the initialisation of the form in the first page of the manual config flow path."""
  201. result = await hass.config_entries.flow.async_init(
  202. DOMAIN, context={"source": "local"}
  203. )
  204. expected = {
  205. "data_schema": ANY,
  206. "description_placeholders": None,
  207. "errors": {},
  208. "flow_id": ANY,
  209. "handler": DOMAIN,
  210. "step_id": "local",
  211. "type": "form",
  212. "last_step": ANY,
  213. "preview": ANY,
  214. }
  215. assert expected == result
  216. # Check the schema. Simple comparison does not work since they are not
  217. # the same object
  218. try:
  219. result["data_schema"](
  220. {CONF_DEVICE_ID: "test", CONF_LOCAL_KEY: TESTKEY, CONF_HOST: "test"}
  221. )
  222. except vol.MultipleInvalid:
  223. assert False
  224. try:
  225. result["data_schema"]({CONF_DEVICE_ID: "missing_some"})
  226. assert False
  227. except vol.MultipleInvalid:
  228. pass
  229. @pytest.mark.asyncio
  230. @patch("custom_components.tuya_local.config_flow.TuyaLocalDevice")
  231. async def test_async_test_connection_valid(mock_device, hass):
  232. """Test that device is returned when connection is valid."""
  233. mock_instance = AsyncMock()
  234. mock_instance.has_returned_state = True
  235. mock_instance.pause = MagicMock()
  236. mock_instance.resume = MagicMock()
  237. mock_device.return_value = mock_instance
  238. hass.data[DOMAIN] = {"deviceid": {"device": mock_instance}}
  239. device = await config_flow.async_test_connection(
  240. {
  241. CONF_DEVICE_ID: "deviceid",
  242. CONF_LOCAL_KEY: TESTKEY,
  243. CONF_HOST: "hostname",
  244. CONF_PROTOCOL_VERSION: "auto",
  245. },
  246. hass,
  247. )
  248. assert device == mock_instance
  249. mock_instance.pause.assert_called_once()
  250. mock_instance.resume.assert_called_once()
  251. @pytest.mark.asyncio
  252. @patch("custom_components.tuya_local.config_flow.TuyaLocalDevice")
  253. async def test_async_test_connection_for_subdevice_valid(mock_device, hass):
  254. """Test that subdevice is returned when connection is valid."""
  255. mock_instance = AsyncMock()
  256. mock_instance.has_returned_state = True
  257. mock_instance.pause = MagicMock()
  258. mock_instance.resume = MagicMock()
  259. mock_device.return_value = mock_instance
  260. hass.data[DOMAIN] = {"subdeviceid": {"device": mock_instance}}
  261. device = await config_flow.async_test_connection(
  262. {
  263. CONF_DEVICE_ID: "deviceid",
  264. CONF_LOCAL_KEY: TESTKEY,
  265. CONF_HOST: "hostname",
  266. CONF_PROTOCOL_VERSION: "auto",
  267. CONF_DEVICE_CID: "subdeviceid",
  268. },
  269. hass,
  270. )
  271. assert device == mock_instance
  272. mock_instance.pause.assert_called_once()
  273. mock_instance.resume.assert_called_once()
  274. @pytest.mark.asyncio
  275. @patch("custom_components.tuya_local.config_flow.TuyaLocalDevice")
  276. async def test_async_test_connection_invalid(mock_device, hass):
  277. """Test that None is returned when connection is invalid."""
  278. mock_instance = AsyncMock()
  279. mock_instance.has_returned_state = False
  280. mock_device.return_value = mock_instance
  281. device = await config_flow.async_test_connection(
  282. {
  283. CONF_DEVICE_ID: "deviceid",
  284. CONF_LOCAL_KEY: TESTKEY,
  285. CONF_HOST: "hostname",
  286. CONF_PROTOCOL_VERSION: "auto",
  287. },
  288. hass,
  289. )
  290. assert device is None
  291. @pytest.mark.asyncio
  292. @patch("custom_components.tuya_local.config_flow.async_test_connection")
  293. async def test_flow_user_init_invalid_config(mock_test, hass):
  294. """Test errors populated when config is invalid."""
  295. mock_test.return_value = None
  296. flow = await hass.config_entries.flow.async_init(
  297. DOMAIN, context={"source": "local"}
  298. )
  299. result = await hass.config_entries.flow.async_configure(
  300. flow["flow_id"],
  301. user_input={
  302. CONF_DEVICE_ID: "deviceid",
  303. CONF_HOST: "hostname",
  304. CONF_LOCAL_KEY: "badkey",
  305. CONF_PROTOCOL_VERSION: "auto",
  306. CONF_POLL_ONLY: False,
  307. },
  308. )
  309. assert {"base": "connection"} == result["errors"]
  310. def setup_device_mock(mock, failure=False, type="test"):
  311. mock_type = MagicMock()
  312. mock_type.legacy_type = type
  313. mock_type.config_type = type
  314. mock_type.match_quality.return_value = 100
  315. mock.async_possible_types = AsyncMock(
  316. return_value=[mock_type] if not failure else []
  317. )
  318. @pytest.mark.asyncio
  319. @patch("custom_components.tuya_local.config_flow.async_test_connection")
  320. async def test_flow_user_init_data_valid(mock_test, hass):
  321. """Test we advance to the next step when connection config is valid."""
  322. mock_device = MagicMock()
  323. setup_device_mock(mock_device)
  324. mock_test.return_value = mock_device
  325. flow = await hass.config_entries.flow.async_init(
  326. DOMAIN, context={"source": "local"}
  327. )
  328. result = await hass.config_entries.flow.async_configure(
  329. flow["flow_id"],
  330. user_input={
  331. CONF_DEVICE_ID: "deviceid",
  332. CONF_HOST: "hostname",
  333. CONF_LOCAL_KEY: TESTKEY,
  334. },
  335. )
  336. assert "form" == result["type"]
  337. assert "select_type" == result["step_id"]
  338. @pytest.mark.asyncio
  339. @patch.object(config_flow.ConfigFlowHandler, "device")
  340. async def test_flow_select_type_init(mock_device, hass):
  341. """Test the initialisation of the form in the 2nd step of the config flow."""
  342. setup_device_mock(mock_device)
  343. result = await hass.config_entries.flow.async_init(
  344. DOMAIN, context={"source": "select_type"}
  345. )
  346. expected = {
  347. "data_schema": ANY,
  348. "description_placeholders": None,
  349. "errors": None,
  350. "flow_id": ANY,
  351. "handler": DOMAIN,
  352. "step_id": "select_type",
  353. "type": "form",
  354. "last_step": ANY,
  355. "preview": ANY,
  356. }
  357. assert expected == result
  358. # Check the schema. Simple comparison does not work since they are not
  359. # the same object
  360. try:
  361. result["data_schema"]({CONF_TYPE: "test"})
  362. except vol.MultipleInvalid:
  363. assert False
  364. try:
  365. result["data_schema"]({CONF_TYPE: "not_test"})
  366. assert False
  367. except vol.MultipleInvalid:
  368. pass
  369. @pytest.mark.asyncio
  370. @patch.object(config_flow.ConfigFlowHandler, "device")
  371. async def test_flow_select_type_aborts_when_no_match(mock_device, hass):
  372. """Test the flow aborts when an unsupported device is used."""
  373. setup_device_mock(mock_device, failure=True)
  374. result = await hass.config_entries.flow.async_init(
  375. DOMAIN, context={"source": "select_type"}
  376. )
  377. assert result["type"] == "abort"
  378. assert result["reason"] == "not_supported"
  379. @pytest.mark.asyncio
  380. @patch.object(config_flow.ConfigFlowHandler, "device")
  381. async def test_flow_select_type_data_valid(mock_device, hass):
  382. """Test the flow continues when valid data is supplied."""
  383. setup_device_mock(mock_device, type="smartplugv1")
  384. flow = await hass.config_entries.flow.async_init(
  385. DOMAIN, context={"source": "select_type"}
  386. )
  387. result = await hass.config_entries.flow.async_configure(
  388. flow["flow_id"],
  389. user_input={CONF_TYPE: "smartplugv1"},
  390. )
  391. assert "form" == result["type"]
  392. assert "choose_entities" == result["step_id"]
  393. @pytest.mark.asyncio
  394. async def test_flow_choose_entities_init(hass):
  395. """Test the initialisation of the form in the 3rd step of the config flow."""
  396. with patch.dict(config_flow.ConfigFlowHandler.data, {CONF_TYPE: "smartplugv1"}):
  397. result = await hass.config_entries.flow.async_init(
  398. DOMAIN, context={"source": "choose_entities"}
  399. )
  400. expected = {
  401. "data_schema": ANY,
  402. "description_placeholders": None,
  403. "errors": None,
  404. "flow_id": ANY,
  405. "handler": DOMAIN,
  406. "step_id": "choose_entities",
  407. "type": "form",
  408. "last_step": ANY,
  409. "preview": ANY,
  410. }
  411. assert expected == result
  412. # Check the schema. Simple comparison does not work since they are not
  413. # the same object
  414. try:
  415. result["data_schema"]({CONF_NAME: "test"})
  416. except vol.MultipleInvalid:
  417. assert False
  418. try:
  419. result["data_schema"]({"climate": True})
  420. assert False
  421. except vol.MultipleInvalid:
  422. pass
  423. @pytest.mark.asyncio
  424. async def test_flow_choose_entities_creates_config_entry(hass, bypass_setup):
  425. """Test the flow ends when data is valid."""
  426. with patch.dict(
  427. config_flow.ConfigFlowHandler.data,
  428. {
  429. CONF_DEVICE_ID: "deviceid",
  430. CONF_LOCAL_KEY: TESTKEY,
  431. CONF_HOST: "hostname",
  432. CONF_POLL_ONLY: False,
  433. CONF_PROTOCOL_VERSION: "auto",
  434. CONF_TYPE: "kogan_kahtp_heater",
  435. CONF_DEVICE_CID: None,
  436. },
  437. ):
  438. flow = await hass.config_entries.flow.async_init(
  439. DOMAIN, context={"source": "choose_entities"}
  440. )
  441. result = await hass.config_entries.flow.async_configure(
  442. flow["flow_id"],
  443. user_input={
  444. CONF_NAME: "test",
  445. },
  446. )
  447. expected = {
  448. "version": 13,
  449. "minor_version": ANY,
  450. "context": {"source": "choose_entities"},
  451. "type": FlowResultType.CREATE_ENTRY,
  452. "flow_id": ANY,
  453. "handler": DOMAIN,
  454. "title": "test",
  455. "description": None,
  456. "description_placeholders": None,
  457. "result": ANY,
  458. "subentries": (),
  459. "options": {},
  460. "data": {
  461. CONF_DEVICE_ID: "deviceid",
  462. CONF_HOST: "hostname",
  463. CONF_LOCAL_KEY: TESTKEY,
  464. CONF_POLL_ONLY: False,
  465. CONF_PROTOCOL_VERSION: "auto",
  466. CONF_TYPE: "kogan_kahtp_heater",
  467. CONF_DEVICE_CID: None,
  468. },
  469. }
  470. assert expected == result
  471. @pytest.mark.asyncio
  472. async def test_options_flow_init(hass):
  473. """Test config flow options."""
  474. config_entry = MockConfigEntry(
  475. domain=DOMAIN,
  476. version=13,
  477. unique_id="uniqueid",
  478. data={
  479. CONF_DEVICE_ID: "deviceid",
  480. CONF_HOST: "hostname",
  481. CONF_LOCAL_KEY: TESTKEY,
  482. CONF_NAME: "test",
  483. CONF_POLL_ONLY: False,
  484. CONF_PROTOCOL_VERSION: "auto",
  485. CONF_TYPE: "smartplugv1",
  486. CONF_DEVICE_CID: "",
  487. },
  488. )
  489. config_entry.add_to_hass(hass)
  490. assert await hass.config_entries.async_setup(config_entry.entry_id)
  491. await hass.async_block_till_done()
  492. # show initial form
  493. result = await hass.config_entries.options.async_init(config_entry.entry_id)
  494. assert "form" == result["type"]
  495. assert "user" == result["step_id"]
  496. assert {} == result["errors"]
  497. assert result["data_schema"](
  498. {
  499. CONF_HOST: "hostname",
  500. CONF_LOCAL_KEY: TESTKEY,
  501. }
  502. )
  503. @pytest.mark.asyncio
  504. @patch("custom_components.tuya_local.config_flow.async_test_connection")
  505. async def test_options_flow_modifies_config(mock_test, hass, bypass_setup):
  506. mock_device = MagicMock()
  507. mock_test.return_value = mock_device
  508. config_entry = MockConfigEntry(
  509. domain=DOMAIN,
  510. version=13,
  511. unique_id="uniqueid",
  512. data={
  513. CONF_DEVICE_ID: "deviceid",
  514. CONF_HOST: "hostname",
  515. CONF_LOCAL_KEY: TESTKEY,
  516. CONF_NAME: "test",
  517. CONF_POLL_ONLY: False,
  518. CONF_PROTOCOL_VERSION: "auto",
  519. CONF_TYPE: "ble_pt216_temp_humidity",
  520. CONF_DEVICE_CID: "subdeviceid",
  521. },
  522. )
  523. config_entry.add_to_hass(hass)
  524. assert await hass.config_entries.async_setup(config_entry.entry_id)
  525. await hass.async_block_till_done()
  526. # show initial form
  527. form = await hass.config_entries.options.async_init(config_entry.entry_id)
  528. # submit updated config
  529. result = await hass.config_entries.options.async_configure(
  530. form["flow_id"],
  531. user_input={
  532. CONF_HOST: "new_hostname",
  533. CONF_LOCAL_KEY: "new_key",
  534. CONF_POLL_ONLY: False,
  535. CONF_PROTOCOL_VERSION: 3.3,
  536. },
  537. )
  538. expected = {
  539. CONF_HOST: "new_hostname",
  540. CONF_LOCAL_KEY: "new_key",
  541. CONF_POLL_ONLY: False,
  542. CONF_PROTOCOL_VERSION: 3.3,
  543. }
  544. assert "create_entry" == result["type"]
  545. assert "" == result["title"]
  546. assert result["result"] is True
  547. assert expected == result["data"]
  548. @pytest.mark.asyncio
  549. @patch("custom_components.tuya_local.config_flow.async_test_connection")
  550. async def test_options_flow_fails_when_connection_fails(mock_test, hass):
  551. mock_test.return_value = None
  552. config_entry = MockConfigEntry(
  553. domain=DOMAIN,
  554. version=13,
  555. unique_id="uniqueid",
  556. data={
  557. CONF_DEVICE_ID: "deviceid",
  558. CONF_HOST: "hostname",
  559. CONF_LOCAL_KEY: TESTKEY,
  560. CONF_NAME: "test",
  561. CONF_POLL_ONLY: False,
  562. CONF_PROTOCOL_VERSION: "auto",
  563. CONF_TYPE: "smartplugv1",
  564. CONF_DEVICE_CID: "",
  565. },
  566. )
  567. config_entry.add_to_hass(hass)
  568. assert await hass.config_entries.async_setup(config_entry.entry_id)
  569. await hass.async_block_till_done()
  570. # show initial form
  571. form = await hass.config_entries.options.async_init(config_entry.entry_id)
  572. # submit updated config
  573. result = await hass.config_entries.options.async_configure(
  574. form["flow_id"],
  575. user_input={
  576. CONF_HOST: "new_hostname",
  577. CONF_LOCAL_KEY: "new_key",
  578. },
  579. )
  580. assert "form" == result["type"]
  581. assert "user" == result["step_id"]
  582. assert {"base": "connection"} == result["errors"]
  583. @pytest.mark.asyncio
  584. @patch("custom_components.tuya_local.config_flow.async_test_connection")
  585. async def test_options_flow_fails_when_config_is_missing(mock_test, hass):
  586. mock_device = MagicMock()
  587. mock_test.return_value = mock_device
  588. config_entry = MockConfigEntry(
  589. domain=DOMAIN,
  590. version=13,
  591. unique_id="uniqueid",
  592. data={
  593. CONF_DEVICE_ID: "deviceid",
  594. CONF_HOST: "hostname",
  595. CONF_LOCAL_KEY: TESTKEY,
  596. CONF_NAME: "test",
  597. CONF_POLL_ONLY: False,
  598. CONF_PROTOCOL_VERSION: "auto",
  599. CONF_TYPE: "non_existing",
  600. },
  601. )
  602. config_entry.add_to_hass(hass)
  603. await hass.config_entries.async_setup(config_entry.entry_id)
  604. await hass.async_block_till_done()
  605. # show initial form
  606. result = await hass.config_entries.options.async_init(config_entry.entry_id)
  607. assert result["type"] == "abort"
  608. assert result["reason"] == "not_supported"