test_config_flow.py 21 KB

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