Beispiel #1
0
async def test_continue_flow_unauth(hass, client, hass_admin_user):
    """Test we can't finish a two step flow."""
    mock_integration(
        hass, MockModule("test",
                         async_setup_entry=AsyncMock(return_value=True)))
    mock_entity_platform(hass, "config_flow.test", None)

    class TestFlow(core_ce.ConfigFlow):
        VERSION = 1

        async def async_step_user(self, user_input=None):
            return self.async_show_form(step_id="account",
                                        data_schema=vol.Schema(
                                            {"user_title": str}))

        async def async_step_account(self, user_input=None):
            return self.async_create_entry(title=user_input["user_title"],
                                           data={"secret": "account_token"})

    with patch.dict(HANDLERS, {"test": TestFlow}):
        resp = await client.post("/api/config/config_entries/flow",
                                 json={"handler": "test"})
        assert resp.status == 200
        data = await resp.json()
        flow_id = data.pop("flow_id")
        assert data == {
            "type": "form",
            "handler": "test",
            "step_id": "account",
            "data_schema": [{
                "name": "user_title",
                "type": "string"
            }],
            "description_placeholders": None,
            "errors": None,
        }

    hass_admin_user.groups = []

    resp = await client.post(
        f"/api/config/config_entries/flow/{flow_id}",
        json={"user_title": "user-title"},
    )
    assert resp.status == 401
async def test_zeroconf(hass):
    """Test we get the form."""
    await setup.async_setup_component(hass, "persistent_notification", {})

    with patch(
            "aioshelly.get_info",
            return_value={
                "mac": "test-mac",
                "type": "SHSW-1",
                "auth": False
            },
    ):
        result = await hass.config_entries.flow.async_init(
            DOMAIN,
            data=DISCOVERY_INFO,
            context={"source": config_entries.SOURCE_ZEROCONF},
        )
        assert result["type"] == "form"
        assert result["errors"] == {}
        context = next(flow["context"]
                       for flow in hass.config_entries.flow.async_progress()
                       if flow["flow_id"] == result["flow_id"])
        assert context["title_placeholders"]["name"] == "shelly1pm-12345"
    with patch(
            "aioshelly.Device.create",
            new=AsyncMock(return_value=Mock(settings=MOCK_SETTINGS, )),
    ), patch("homeassistant.components.shelly.async_setup",
             return_value=True) as mock_setup, patch(
                 "homeassistant.components.shelly.async_setup_entry",
                 return_value=True,
             ) as mock_setup_entry:
        result2 = await hass.config_entries.flow.async_configure(
            result["flow_id"],
            {},
        )
        await hass.async_block_till_done()

    assert result2["type"] == "create_entry"
    assert result2["title"] == "Test name"
    assert result2["data"] == {
        "host": "1.1.1.1",
    }
    assert len(mock_setup.mock_calls) == 1
    assert len(mock_setup_entry.mock_calls) == 1
Beispiel #3
0
def patch_cluster(cluster):
    """Patch a cluster for testing."""
    cluster.bind = AsyncMock(return_value=[0])
    cluster.configure_reporting = AsyncMock(return_value=[0])
    cluster.deserialize = Mock()
    cluster.handle_cluster_request = Mock()
    cluster.read_attributes = AsyncMock(return_value=[{}, {}])
    cluster.read_attributes_raw = Mock()
    cluster.unbind = AsyncMock(return_value=[0])
    cluster.write_attributes = AsyncMock(
        return_value=[zcl_f.WriteAttributesResponse.deserialize(b"\x00")[0]])
    if cluster.cluster_id == 4:
        cluster.add = AsyncMock(return_value=[0])
Beispiel #4
0
async def test_immediate_works(hass):
    """Test immediate works."""
    calls = []
    debouncer = debounce.Debouncer(
        hass,
        None,
        cooldown=0.01,
        immediate=True,
        function=AsyncMock(side_effect=lambda: calls.append(None)),
    )

    # Call when nothing happening
    await debouncer.async_call()
    assert len(calls) == 1
    assert debouncer._timer_task is not None
    assert debouncer._execute_at_end_of_timer is False

    # Call when cooldown active setting execute at end to True
    await debouncer.async_call()
    assert len(calls) == 1
    assert debouncer._timer_task is not None
    assert debouncer._execute_at_end_of_timer is True

    # Canceling debounce in cooldown
    debouncer.async_cancel()
    assert debouncer._timer_task is None
    assert debouncer._execute_at_end_of_timer is False

    # Call and let timer run out
    await debouncer.async_call()
    assert len(calls) == 2
    await debouncer._handle_timer_finish()
    assert len(calls) == 2
    assert debouncer._timer_task is None
    assert debouncer._execute_at_end_of_timer is False

    # Test calling doesn't execute/cooldown if currently executing.
    await debouncer._execute_lock.acquire()
    await debouncer.async_call()
    assert len(calls) == 2
    assert debouncer._timer_task is None
    assert debouncer._execute_at_end_of_timer is False
    debouncer._execute_lock.release()
Beispiel #5
0
async def test_discovery_cannot_connect_ws(hass):
    """Test discovery aborts if cannot connect to websocket."""
    with patch(
            "homeassistant.components.kodi.config_flow.Kodi.ping",
            return_value=True,
    ), patch.object(
            MockWSConnection,
            "connect",
            AsyncMock(side_effect=CannotConnectError),
    ), patch(
            "homeassistant.components.kodi.config_flow.get_kodi_connection",
            new=get_kodi_connection,
    ):
        result = await hass.config_entries.flow.async_init(
            DOMAIN, context={"source": "zeroconf"}, data=TEST_DISCOVERY)

    assert result["type"] == "form"
    assert result["step_id"] == "ws_port"
    assert result["errors"] == {}
Beispiel #6
0
async def test_call_with_one_of_required_features(hass, mock_entities):
    """Test service calls invoked with one entity having the required features."""
    test_service_mock = AsyncMock(return_value=None)
    await service.entity_service_call(
        hass,
        [Mock(entities=mock_entities)],
        test_service_mock,
        ha.ServiceCall("test_domain", "test_service", {"entity_id": "all"}),
        required_features=[SUPPORT_A, SUPPORT_C],
    )

    assert test_service_mock.call_count == 3
    expected = [
        mock_entities["light.kitchen"],
        mock_entities["light.bedroom"],
        mock_entities["light.bathroom"],
    ]
    actual = [call[0][0] for call in test_service_mock.call_args_list]
    assert all(entity in actual for entity in expected)
Beispiel #7
0
async def test_handle_unauthorized(hass):
    """Test handling an unauthorized error on update."""
    entry = Mock(async_setup=AsyncMock())
    entry.data = {"host": "1.2.3.4", "username": "******"}
    hue_bridge = bridge.HueBridge(hass, entry, False, False)

    with patch.object(bridge, "authenticate_bridge",
                      return_value=Mock()), patch("aiohue.Bridge",
                                                  return_value=Mock()):
        assert await hue_bridge.async_setup() is True

    assert hue_bridge.authorized is True

    with patch.object(bridge, "create_config_flow") as mock_create:
        await hue_bridge.handle_unauthorized_error()

    assert hue_bridge.authorized is False
    assert len(mock_create.mock_calls) == 1
    assert mock_create.mock_calls[0][1][1] == "1.2.3.4"
Beispiel #8
0
async def test_form_errors_test_connection(hass, error):
    """Test we handle errors."""
    exc, base_error = error
    result = await hass.config_entries.flow.async_init(
        DOMAIN, context={"source": config_entries.SOURCE_USER})

    with patch("aioshelly.get_info",
               return_value={
                   "mac": "test-mac",
                   "auth": False
               }), patch("aioshelly.Device.create",
                         new=AsyncMock(side_effect=exc)):
        result2 = await hass.config_entries.flow.async_configure(
            result["flow_id"],
            {"host": "1.1.1.1"},
        )

    assert result2["type"] == "form"
    assert result2["errors"] == {"base": base_error}
Beispiel #9
0
async def test_yaml_updates_update_config_entry_for_name(hass):
    """Test async_setup with imported config."""
    entry = MockConfigEntry(
        domain=DOMAIN,
        source=SOURCE_IMPORT,
        data={
            CONF_NAME: BRIDGE_NAME,
            CONF_PORT: DEFAULT_PORT
        },
        options={},
    )
    entry.add_to_hass(hass)

    with patch(f"{PATH_HOMEKIT}.HomeKit") as mock_homekit:
        mock_homekit.return_value = homekit = Mock()
        type(homekit).async_start = AsyncMock()
        assert await async_setup_component(
            hass, "homekit",
            {"homekit": {
                CONF_NAME: BRIDGE_NAME,
                CONF_PORT: 12345
            }})
        await hass.async_block_till_done()

    mock_homekit.assert_any_call(
        hass,
        BRIDGE_NAME,
        12345,
        None,
        ANY,
        {},
        DEFAULT_SAFE_MODE,
        None,
        entry.entry_id,
    )
    assert mock_homekit().setup.called is True

    # Test auto start enabled
    mock_homekit.reset_mock()
    hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
    await hass.async_block_till_done()

    mock_homekit().async_start.assert_called()
Beispiel #10
0
async def test_bridge_setup(hass):
    """Test a successful setup."""
    entry = Mock()
    api = Mock(initialize=AsyncMock())
    entry.data = {"host": "1.2.3.4", "username": "******"}
    entry.options = {
        CONF_ALLOW_HUE_GROUPS: False,
        CONF_ALLOW_UNREACHABLE: False
    }
    hue_bridge = bridge.HueBridge(hass, entry)

    with patch("aiohue.Bridge", return_value=api), patch.object(
            hass.config_entries, "async_forward_entry_setup") as mock_forward:
        assert await hue_bridge.async_setup() is True

    assert hue_bridge.api is api
    assert len(mock_forward.mock_calls) == 3
    forward_entries = {c[1][1] for c in mock_forward.mock_calls}
    assert forward_entries == {"light", "binary_sensor", "sensor"}
Beispiel #11
0
async def test_only_valid_components(hass, mqtt_mock, caplog):
    """Test for a valid component."""
    with patch("homeassistant.components.mqtt.discovery.async_dispatcher_send"
               ) as mock_dispatcher_send:
        entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0]

        invalid_component = "timer"

        mock_dispatcher_send = AsyncMock(return_value=None)
        await async_start(hass, "homeassistant", entry)

        async_fire_mqtt_message(
            hass, f"homeassistant/{invalid_component}/bla/config", "{}")

    await hass.async_block_till_done()

    assert f"Integration {invalid_component} is not supported" in caplog.text

    assert not mock_dispatcher_send.called
async def test_form_empty_ws_port(hass, user_flow):
    """Test we handle an empty websocket port input."""
    with patch(
        "homeassistant.components.kodi.config_flow.Kodi.ping",
        return_value=True,
    ), patch.object(
        MockWSConnection,
        "connect",
        AsyncMock(side_effect=CannotConnectError),
    ), patch(
        "homeassistant.components.kodi.config_flow.get_kodi_connection",
        new=get_kodi_connection,
    ):
        result = await hass.config_entries.flow.async_configure(user_flow, TEST_HOST)

    assert result["type"] == "form"
    assert result["step_id"] == "ws_port"
    assert result["errors"] == {}

    with patch(
        "homeassistant.components.kodi.async_setup", return_value=True
    ) as mock_setup, patch(
        "homeassistant.components.kodi.async_setup_entry",
        return_value=True,
    ) as mock_setup_entry:
        result = await hass.config_entries.flow.async_configure(
            result["flow_id"], {"ws_port": 0}
        )

    assert result["type"] == "create_entry"
    assert result["title"] == TEST_HOST["host"]
    assert result["data"] == {
        **TEST_HOST,
        "ws_port": None,
        "password": None,
        "username": None,
        "name": None,
        "timeout": DEFAULT_TIMEOUT,
    }

    await hass.async_block_till_done()
    assert len(mock_setup.mock_calls) == 1
    assert len(mock_setup_entry.mock_calls) == 1
async def test_no_interface(hass):
    """Test creating an AsusWRT scanner using no interface."""
    with patch("homeassistant.components.asuswrt.AsusWrt") as AsusWrt:
        AsusWrt().connection.async_connect = AsyncMock()
        AsusWrt().is_connected = False
        result = await async_setup_component(
            hass,
            DOMAIN,
            {
                DOMAIN: {
                    CONF_HOST: "fake_host",
                    CONF_USERNAME: "******",
                    CONF_PASSWORD: "******",
                    CONF_DNSMASQ: "/",
                    CONF_INTERFACE: None,
                }
            },
        )
        assert not result
Beispiel #14
0
async def test_flow_link_unknown_host(hass):
    """Test config flow ."""
    mock_bridge = get_mock_bridge(mock_create_user=AsyncMock(
        side_effect=client_exceptions.ClientOSError), )
    with patch(
            "homeassistant.components.hue.config_flow.discover_nupnp",
            return_value=[mock_bridge],
    ):
        result = await hass.config_entries.flow.async_init(
            const.DOMAIN, context={"source": "user"})

    result = await hass.config_entries.flow.async_configure(
        result["flow_id"], user_input={"id": mock_bridge.id})

    result = await hass.config_entries.flow.async_configure(result["flow_id"],
                                                            user_input={})

    assert result["type"] == "abort"
    assert result["reason"] == "cannot_connect"
Beispiel #15
0
async def test_title_without_name_and_prefix(hass):
    """Test we set the title to the hostname when the device doesn't have a name."""
    await setup.async_setup_component(hass, "persistent_notification", {})
    result = await hass.config_entries.flow.async_init(
        DOMAIN, context={"source": config_entries.SOURCE_USER}
    )
    assert result["type"] == "form"
    assert result["errors"] == {}

    settings = MOCK_SETTINGS.copy()
    settings["name"] = None
    settings["device"] = settings["device"].copy()
    settings["device"]["hostname"] = "shelly1pm-12345"
    with patch(
        "aioshelly.get_info",
        return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False},
    ), patch(
        "aioshelly.Device.create",
        new=AsyncMock(
            return_value=Mock(
                settings=settings,
            )
        ),
    ), patch(
        "homeassistant.components.shelly.async_setup", return_value=True
    ) as mock_setup, patch(
        "homeassistant.components.shelly.async_setup_entry",
        return_value=True,
    ) as mock_setup_entry:
        result2 = await hass.config_entries.flow.async_configure(
            result["flow_id"],
            {"host": "1.1.1.1"},
        )
        await hass.async_block_till_done()

    assert result2["type"] == "create_entry"
    assert result2["title"] == "shelly1pm-12345"
    assert result2["data"] == {
        "host": "1.1.1.1",
    }
    assert len(mock_setup.mock_calls) == 1
    assert len(mock_setup_entry.mock_calls) == 1
Beispiel #16
0
async def test_turn_on_failure(feature, hass, config, caplog):
    """Test that turn_on failures are logged."""

    caplog.set_level(logging.ERROR)

    feature_mock, entity_id = feature
    feature_mock.async_on = AsyncMock(
        side_effect=blebox_uniapi.error.BadOnValueError)
    await async_setup_entity(hass, config, entity_id)

    feature_mock.sensible_on_value = 123
    await hass.services.async_call(
        "light",
        SERVICE_TURN_ON,
        {"entity_id": entity_id},
        blocking=True,
    )

    assert (f"Turning on '{feature_mock.full_name}' failed: Bad value 123 ()"
            in caplog.text)
async def test_multiple_refreshing():
    EXPIRED_TOKEN = "old access token"
    REFRESHED_TOKEN = "refreshed access token"

    def raise_on_old_token(*args, **kwargs):
        if http_client._access_token == EXPIRED_TOKEN:
            raise AuthenticationRequired()
        return 'ok'

    http_client = AuthenticatedHttpClient(Mock, Mock)
    http_client._access_token = EXPIRED_TOKEN
    http_client.get_access_token = AsyncMockDelayed(
        return_value=REFRESHED_TOKEN)
    http_client._oauth_request = AsyncMock(side_effect=raise_on_old_token)
    responses = await asyncio.gather(
        http_client.request('url'),
        http_client.request('url'),
    )
    for i in responses:
        assert i == 'ok'
Beispiel #18
0
    def test_install_game_game_installed(create_authenticated_plugin):
        loop = asyncio.get_event_loop()
        pg = create_authenticated_plugin()

        new_game = NewGame()
        new_game.status = "Installed"

        pg.user_can_perform_actions.return_value = True

        pg.games_collection = [new_game]

        pg.open_uplay_client = mock.create_autospec(pg.open_uplay_client)

        pg.launch_game = AsyncMock(return_value=None)

        with mock.patch("plugin.subprocess.Popen") as pop:
            loop.run_until_complete(pg.install_game("321"))
            pop.assert_not_called()

        pg.launch_game.asert_called()
Beispiel #19
0
async def test_flow_link_unknown_error(hass):
    """Test if a unknown error happened during the linking processes."""
    mock_bridge = get_mock_bridge(
        mock_create_user=AsyncMock(side_effect=OSError), )
    with patch(
            "homeassistant.components.hue.config_flow.discover_nupnp",
            return_value=[mock_bridge],
    ):
        result = await hass.config_entries.flow.async_init(
            const.DOMAIN, context={"source": "user"})

    result = await hass.config_entries.flow.async_configure(
        result["flow_id"], user_input={"id": mock_bridge.id})

    result = await hass.config_entries.flow.async_configure(result["flow_id"],
                                                            user_input={})

    assert result["type"] == "form"
    assert result["step_id"] == "link"
    assert result["errors"] == {"base": "linking"}
async def test_update(airsensor, hass, config):
    """Test air quality sensor state after update."""

    feature_mock, entity_id = airsensor

    def initial_update():
        feature_mock.pm1 = 49
        feature_mock.pm2_5 = 222
        feature_mock.pm10 = 333

    feature_mock.async_update = AsyncMock(side_effect=initial_update)
    await async_setup_entity(hass, config, entity_id)

    state = hass.states.get(entity_id)

    assert state.attributes[ATTR_PM_0_1] == 49
    assert state.attributes[ATTR_PM_2_5] == 222
    assert state.attributes[ATTR_PM_10] == 333

    assert state.state == "222"
Beispiel #21
0
async def test_flow_link_button_not_pressed(hass):
    """Test config flow ."""
    mock_bridge = get_mock_bridge(
        mock_create_user=AsyncMock(side_effect=aiohue.LinkButtonNotPressed), )
    with patch(
            "homeassistant.components.hue.config_flow.discover_nupnp",
            return_value=[mock_bridge],
    ):
        result = await hass.config_entries.flow.async_init(
            const.DOMAIN, context={"source": "user"})

    result = await hass.config_entries.flow.async_configure(
        result["flow_id"], user_input={"id": mock_bridge.id})

    result = await hass.config_entries.flow.async_configure(result["flow_id"],
                                                            user_input={})

    assert result["type"] == "form"
    assert result["step_id"] == "link"
    assert result["errors"] == {"base": "register_failed"}
async def test_login_recovers_bad_internet(hass, caplog):
    """Test Alexa can recover bad auth."""
    prefs = Mock(
        alexa_enabled=True,
        google_enabled=False,
        async_set_username=AsyncMock(return_value=None),
    )
    client = CloudClient(hass, prefs, None, {}, {})
    client.cloud = Mock()
    client._alexa_config = Mock(
        async_enable_proactive_mode=Mock(side_effect=aiohttp.ClientError)
    )
    await client.logged_in()
    assert len(client._alexa_config.async_enable_proactive_mode.mock_calls) == 1
    assert "Unable to activate Alexa Report State" in caplog.text

    async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
    await hass.async_block_till_done()

    assert len(client._alexa_config.async_enable_proactive_mode.mock_calls) == 2
async def test_import_cannot_connect(hass: HomeAssistantType) -> None:
    """Check an import flow that cannot connect."""

    client = create_mock_client()
    client.async_client_connect = AsyncMock(return_value=False)

    with patch("homeassistant.components.hyperion.client.HyperionClient",
               return_value=client):
        result = await _init_flow(
            hass,
            source=SOURCE_IMPORT,
            data={
                CONF_HOST: TEST_HOST,
                CONF_PORT: TEST_PORT,
            },
        )
        await hass.async_block_till_done()

    assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
    assert result["reason"] == "cannot_connect"
async def test_zeroconf(hass):
    """Test we get the form."""
    await setup.async_setup_component(hass, "persistent_notification", {})

    with patch(
        "aioshelly.get_info",
        return_value={"mac": "test-mac", "type": "SHSW-1", "auth": False},
    ):
        result = await hass.config_entries.flow.async_init(
            DOMAIN,
            data={"host": "1.1.1.1", "name": "shelly1pm-12345"},
            context={"source": config_entries.SOURCE_ZEROCONF},
        )
        assert result["type"] == "form"
        assert result["errors"] == {}

    with patch(
        "aioshelly.Device.create",
        return_value=Mock(
            shutdown=AsyncMock(),
            settings={"name": "Test name", "device": {"mac": "test-mac"}},
        ),
    ), patch(
        "homeassistant.components.shelly.async_setup", return_value=True
    ) as mock_setup, patch(
        "homeassistant.components.shelly.async_setup_entry",
        return_value=True,
    ) as mock_setup_entry:
        result2 = await hass.config_entries.flow.async_configure(
            result["flow_id"],
            {},
        )

    assert result2["type"] == "create_entry"
    assert result2["title"] == "Test name"
    assert result2["data"] == {
        "host": "1.1.1.1",
    }
    await hass.async_block_till_done()
    assert len(mock_setup.mock_calls) == 1
    assert len(mock_setup_entry.mock_calls) == 1
async def test_setup_entry(hass):
    """Test setup entry calls async_setup_entry on platform."""
    mock_setup_entry = AsyncMock(return_value=True)
    mock_entity_platform(
        hass,
        "test_domain.entry_domain",
        MockPlatform(async_setup_entry=mock_setup_entry,
                     scan_interval=timedelta(seconds=5)),
    )

    component = EntityComponent(_LOGGER, DOMAIN, hass)
    entry = MockConfigEntry(domain="entry_domain")

    assert await component.async_setup_entry(entry)
    assert len(mock_setup_entry.mock_calls) == 1
    p_hass, p_entry, _ = mock_setup_entry.mock_calls[0][1]
    assert p_hass is hass
    assert p_entry is entry

    assert component._platforms[entry.entry_id].scan_interval == timedelta(
        seconds=5)
def cast_mock():
    """Mock pychromecast."""
    pycast_mock = MagicMock()
    pycast_mock.start_discovery.return_value = (None, Mock())
    dial_mock = MagicMock(name="XXX")
    dial_mock.get_device_status.return_value.uuid = "fake_uuid"
    dial_mock.get_device_status.return_value.manufacturer = "fake_manufacturer"
    dial_mock.get_device_status.return_value.model_name = "fake_model_name"
    dial_mock.get_device_status.return_value.friendly_name = "fake_friendly_name"

    with patch(
        "homeassistant.components.cast.media_player.pychromecast", pycast_mock
    ), patch(
        "homeassistant.components.cast.discovery.pychromecast", pycast_mock
    ), patch(
        "homeassistant.components.cast.media_player.MultizoneManager", MagicMock()
    ), patch(
        "homeassistant.components.cast.media_player.zeroconf.async_get_instance",
        AsyncMock(),
    ):
        yield
Beispiel #27
0
def get_mock_bridge(
    bridge_id="aabbccddeeff", host="1.2.3.4", mock_create_user=None, username=None
):
    """Return a mock bridge."""
    mock_bridge = Mock()
    mock_bridge.host = host
    mock_bridge.username = username
    mock_bridge.config.name = "Mock Bridge"
    mock_bridge.id = bridge_id

    if not mock_create_user:

        async def create_user(username):
            mock_bridge.username = username

        mock_create_user = create_user

    mock_bridge.create_user = mock_create_user
    mock_bridge.initialize = AsyncMock()

    return mock_bridge
def mock_api_fixture() -> Generator[AsyncMock, Any, None]:
    """Fixture for mocking aioswitcher.api.SwitcherV2Api."""
    mock_api = AsyncMock()

    patchers = [
        patch(
            "homeassistant.components.switcher_kis.SwitcherV2Api.connect", new=mock_api
        ),
        patch(
            "homeassistant.components.switcher_kis.SwitcherV2Api.disconnect",
            new=mock_api,
        ),
    ]

    for patcher in patchers:
        patcher.start()

    yield

    for patcher in patchers:
        patcher.stop()
def create_valid_feature_mock(path="homeassistant.components.blebox.Products"):
    """Return a valid, complete BleBox feature mock."""
    feature = mock_only_feature(
        blebox_uniapi.cover.Cover,
        unique_id="BleBox-gateBox-1afe34db9437-0.position",
        full_name="gateBox-0.position",
        device_class="gate",
        state=0,
        async_update=AsyncMock(),
        current=None,
    )

    product = setup_product_mock("covers", [feature], path)

    type(product).name = PropertyMock(return_value="My gate controller")
    type(product).model = PropertyMock(return_value="gateController")
    type(product).type = PropertyMock(return_value="gateBox")
    type(product).brand = PropertyMock(return_value="BleBox")
    type(product).firmware_version = PropertyMock(return_value="1.23")
    type(product).unique_id = PropertyMock(return_value="abcd0123ef5678")

    return feature
async def test_unload_entry_resets_platform(hass):
    """Test unloading an entry removes all entities."""
    mock_setup_entry = AsyncMock(return_value=True)
    mock_entity_platform(
        hass,
        "test_domain.entry_domain",
        MockPlatform(async_setup_entry=mock_setup_entry),
    )

    component = EntityComponent(_LOGGER, DOMAIN, hass)
    entry = MockConfigEntry(domain="entry_domain")

    assert await component.async_setup_entry(entry)
    assert len(mock_setup_entry.mock_calls) == 1
    add_entities = mock_setup_entry.mock_calls[0][1][2]
    add_entities([MockEntity()])
    await hass.async_block_till_done()

    assert len(hass.states.async_entity_ids()) == 1

    assert await component.async_unload_entry(entry)
    assert len(hass.states.async_entity_ids()) == 0