def test_registry_respect_entity_namespace(hass):
    """Test that the registry respects entity namespace."""
    mock_registry(hass)
    platform = MockEntityPlatform(hass, entity_namespace='ns')
    entity = MockEntity(unique_id='1234', name='Device Name')
    yield from platform.async_add_entities([entity])
    assert entity.entity_id == 'test_domain.ns_device_name'
def test_registry_respect_entity_disabled(hass):
    """Test that the registry respects entity disabled."""
    mock_registry(hass, {
        'test_domain.world': entity_registry.RegistryEntry(
            entity_id='test_domain.world',
            unique_id='1234',
            # Using component.async_add_entities is equal to platform "domain"
            platform='test_platform',
            disabled_by=entity_registry.DISABLED_USER
        )
    })
    platform = MockEntityPlatform(hass)
    entity = MockEntity(unique_id='1234')
    yield from platform.async_add_entities([entity])
    assert entity.entity_id is None
    assert hass.states.async_entity_ids() == []
async def test_reset_cancels_retry_setup_when_not_started(hass):
    """Test that resetting a platform will cancel scheduled a setup retry when not yet started."""
    hass.state = CoreState.starting
    async_setup_entry = Mock(side_effect=PlatformNotReady)
    initial_listeners = hass.bus.async_listeners()[EVENT_HOMEASSISTANT_STARTED]

    platform = MockPlatform(async_setup_entry=async_setup_entry)
    config_entry = MockConfigEntry()
    ent_platform = MockEntityPlatform(
        hass, platform_name=config_entry.domain, platform=platform
    )

    assert not await ent_platform.async_setup_entry(config_entry)
    await hass.async_block_till_done()
    assert (
        hass.bus.async_listeners()[EVENT_HOMEASSISTANT_STARTED] == initial_listeners + 1
    )
    assert ent_platform._async_cancel_retry_setup is not None

    await ent_platform.async_reset()
    await hass.async_block_till_done()
    assert hass.bus.async_listeners()[EVENT_HOMEASSISTANT_STARTED] == initial_listeners
    assert ent_platform._async_cancel_retry_setup is None
async def test_setup_entry_platform_not_ready_from_exception(hass, caplog):
    """Test when an entry is not ready yet that includes the causing exception string."""
    original_exception = HomeAssistantError("The device dropped the connection")
    platform_exception = PlatformNotReady()
    platform_exception.__cause__ = original_exception

    async_setup_entry = Mock(side_effect=platform_exception)
    platform = MockPlatform(async_setup_entry=async_setup_entry)
    config_entry = MockConfigEntry()
    ent_platform = MockEntityPlatform(
        hass, platform_name=config_entry.domain, platform=platform
    )

    with patch.object(entity_platform, "async_call_later") as mock_call_later:
        assert not await ent_platform.async_setup_entry(config_entry)

    full_name = f"{ent_platform.domain}.{config_entry.domain}"
    assert full_name not in hass.config.components
    assert len(async_setup_entry.mock_calls) == 1

    assert "Platform test not ready yet" in caplog.text
    assert "The device dropped the connection" in caplog.text
    assert len(mock_call_later.mock_calls) == 1
示例#5
0
async def test_setup_entry(opp):
    """Test we can setup an entry."""
    registry = mock_registry(opp)

    async def async_setup_entry(opp, config_entry, async_add_entities):
        """Mock setup entry method."""
        async_add_entities([MockEntity(name="test1", unique_id="unique")])
        return True

    platform = MockPlatform(async_setup_entry=async_setup_entry)
    config_entry = MockConfigEntry(entry_id="super-mock-id")
    entity_platform = MockEntityPlatform(opp,
                                         platform_name=config_entry.domain,
                                         platform=platform)

    assert await entity_platform.async_setup_entry(config_entry)
    await opp.async_block_till_done()
    full_name = f"{entity_platform.domain}.{config_entry.domain}"
    assert full_name in opp.config.components
    assert len(opp.states.async_entity_ids()) == 1
    assert len(registry.entities) == 1
    assert registry.entities[
        "test_domain.test1"].config_entry_id == "super-mock-id"
async def test_setup_entry(hass):
    """Test we can setup an entry."""
    registry = mock_registry(hass)

    async def async_setup_entry(hass, config_entry, async_add_entities):
        """Mock setup entry method."""
        async_add_entities([MockEntity(name='test1', unique_id='unique')])
        return True

    platform = MockPlatform(async_setup_entry=async_setup_entry)
    config_entry = MockConfigEntry(entry_id='super-mock-id')
    entity_platform = MockEntityPlatform(hass,
                                         platform_name=config_entry.domain,
                                         platform=platform)

    assert await entity_platform.async_setup_entry(config_entry)
    await hass.async_block_till_done()
    full_name = '{}.{}'.format(entity_platform.domain, config_entry.domain)
    assert full_name in hass.config.components
    assert len(hass.states.async_entity_ids()) == 1
    assert len(registry.entities) == 1
    assert registry.entities['test_domain.test1'].config_entry_id == \
        'super-mock-id'
async def test_update_entity_no_changes(hass, client):
    """Test update entity with no changes."""
    mock_registry(
        hass,
        {
            'test_domain.world':
            RegistryEntry(
                entity_id='test_domain.world',
                unique_id='1234',
                # Using component.async_add_entities is equal to platform "domain"
                platform='test_platform',
                name='name of entity')
        })
    platform = MockEntityPlatform(hass)
    entity = MockEntity(unique_id='1234')
    await platform.async_add_entities([entity])

    state = hass.states.get('test_domain.world')
    assert state is not None
    assert state.name == 'name of entity'

    await client.send_json({
        'id': 6,
        'type': 'config/entity_registry/update',
        'entity_id': 'test_domain.world',
        'name': 'name of entity',
    })

    msg = await client.receive_json()

    assert msg['result'] == {
        'entity_id': 'test_domain.world',
        'name': 'name of entity'
    }

    state = hass.states.get('test_domain.world')
    assert state.name == 'name of entity'
async def test_entity_disabled_by_device(hass: HomeAssistant):
    """Test entity disabled by device."""

    connections = {(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}
    entity_disabled = MockEntity(
        unique_id="disabled", device_info=DeviceInfo(connections=connections)
    )

    async def async_setup_entry(hass, config_entry, async_add_entities):
        """Mock setup entry method."""
        async_add_entities([entity_disabled])
        return True

    platform = MockPlatform(async_setup_entry=async_setup_entry)
    config_entry = MockConfigEntry(entry_id="super-mock-id", domain=DOMAIN)
    entity_platform = MockEntityPlatform(
        hass, platform_name=config_entry.domain, platform=platform
    )

    device_registry = dr.async_get(hass)
    device_registry.async_get_or_create(
        config_entry_id=config_entry.entry_id,
        connections=connections,
        disabled_by=dr.DeviceEntryDisabler.USER,
    )

    assert await entity_platform.async_setup_entry(config_entry)
    await hass.async_block_till_done()

    assert entity_disabled.hass is None
    assert entity_disabled.platform is None

    registry = er.async_get(hass)

    entry_disabled = registry.async_get_or_create(DOMAIN, DOMAIN, "disabled")
    assert entry_disabled.disabled_by is er.RegistryEntryDisabler.DEVICE
async def test_reset_cancels_retry_setup(hass):
    """Test that resetting a platform will cancel scheduled a setup retry."""
    async_setup_entry = Mock(side_effect=PlatformNotReady)
    platform = MockPlatform(
        async_setup_entry=async_setup_entry
    )
    config_entry = MockConfigEntry()
    ent_platform = MockEntityPlatform(
        hass,
        platform_name=config_entry.domain,
        platform=platform
    )

    with patch.object(entity_platform, 'async_call_later') as mock_call_later:
        assert not await ent_platform.async_setup_entry(config_entry)

    assert len(mock_call_later.mock_calls) == 1
    assert len(mock_call_later.return_value.mock_calls) == 0
    assert ent_platform._async_cancel_retry_setup is not None

    await ent_platform.async_reset()

    assert len(mock_call_later.return_value.mock_calls) == 1
    assert ent_platform._async_cancel_retry_setup is None
示例#10
0
async def test_entity_source_admin(hass, websocket_client, hass_admin_user):
    """Check that we fetch sources correctly."""
    platform = MockEntityPlatform(hass)

    await platform.async_add_entities(
        [MockEntity(name="Entity 1"), MockEntity(name="Entity 2")]
    )

    # Fetch all
    await websocket_client.send_json({"id": 6, "type": "entity/source"})

    msg = await websocket_client.receive_json()
    assert msg["id"] == 6
    assert msg["type"] == const.TYPE_RESULT
    assert msg["success"]
    assert msg["result"] == {
        "test_domain.entity_1": {
            "source": entity.SOURCE_PLATFORM_CONFIG,
            "domain": "test_platform",
        },
        "test_domain.entity_2": {
            "source": entity.SOURCE_PLATFORM_CONFIG,
            "domain": "test_platform",
        },
    }

    # Fetch one
    await websocket_client.send_json(
        {"id": 7, "type": "entity/source", "entity_id": ["test_domain.entity_2"]}
    )

    msg = await websocket_client.receive_json()
    assert msg["id"] == 7
    assert msg["type"] == const.TYPE_RESULT
    assert msg["success"]
    assert msg["result"] == {
        "test_domain.entity_2": {
            "source": entity.SOURCE_PLATFORM_CONFIG,
            "domain": "test_platform",
        },
    }

    # Fetch two
    await websocket_client.send_json(
        {
            "id": 8,
            "type": "entity/source",
            "entity_id": ["test_domain.entity_2", "test_domain.entity_1"],
        }
    )

    msg = await websocket_client.receive_json()
    assert msg["id"] == 8
    assert msg["type"] == const.TYPE_RESULT
    assert msg["success"]
    assert msg["result"] == {
        "test_domain.entity_1": {
            "source": entity.SOURCE_PLATFORM_CONFIG,
            "domain": "test_platform",
        },
        "test_domain.entity_2": {
            "source": entity.SOURCE_PLATFORM_CONFIG,
            "domain": "test_platform",
        },
    }

    # Fetch non existing
    await websocket_client.send_json(
        {
            "id": 9,
            "type": "entity/source",
            "entity_id": ["test_domain.entity_2", "test_domain.non_existing"],
        }
    )

    msg = await websocket_client.receive_json()
    assert msg["id"] == 9
    assert msg["type"] == const.TYPE_RESULT
    assert not msg["success"]
    assert msg["error"]["code"] == const.ERR_NOT_FOUND

    # Mock policy
    hass_admin_user.groups = []
    hass_admin_user.mock_policy(
        {"entities": {"entity_ids": {"test_domain.entity_2": True}}}
    )

    # Fetch all
    await websocket_client.send_json({"id": 10, "type": "entity/source"})

    msg = await websocket_client.receive_json()
    assert msg["id"] == 10
    assert msg["type"] == const.TYPE_RESULT
    assert msg["success"]
    assert msg["result"] == {
        "test_domain.entity_2": {
            "source": entity.SOURCE_PLATFORM_CONFIG,
            "domain": "test_platform",
        },
    }

    # Fetch unauthorized
    await websocket_client.send_json(
        {"id": 11, "type": "entity/source", "entity_id": ["test_domain.entity_1"]}
    )

    msg = await websocket_client.receive_json()
    assert msg["id"] == 11
    assert msg["type"] == const.TYPE_RESULT
    assert not msg["success"]
    assert msg["error"]["code"] == const.ERR_UNAUTHORIZED
async def test_device_info_called(hass):
    """Test device info is forwarded correctly."""
    registry = dr.async_get(hass)
    via = registry.async_get_or_create(
        config_entry_id="123",
        connections=set(),
        identifiers={("hue", "via-id")},
        manufacturer="manufacturer",
        model="via",
    )

    async def async_setup_entry(hass, config_entry, async_add_entities):
        """Mock setup entry method."""
        async_add_entities(
            [
                # Invalid device info
                MockEntity(unique_id="abcd", device_info={}),
                # Valid device info
                MockEntity(
                    unique_id="qwer",
                    device_info={
                        "identifiers": {("hue", "1234")},
                        "configuration_url": "http://192.168.0.100/config",
                        "connections": {(dr.CONNECTION_NETWORK_MAC, "abcd")},
                        "manufacturer": "test-manuf",
                        "model": "test-model",
                        "name": "test-name",
                        "sw_version": "test-sw",
                        "hw_version": "test-hw",
                        "suggested_area": "Heliport",
                        "entry_type": dr.DeviceEntryType.SERVICE,
                        "via_device": ("hue", "via-id"),
                    },
                ),
            ]
        )
        return True

    platform = MockPlatform(async_setup_entry=async_setup_entry)
    config_entry = MockConfigEntry(entry_id="super-mock-id")
    entity_platform = MockEntityPlatform(
        hass, platform_name=config_entry.domain, platform=platform
    )

    assert await entity_platform.async_setup_entry(config_entry)
    await hass.async_block_till_done()

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

    device = registry.async_get_device({("hue", "1234")})
    assert device is not None
    assert device.identifiers == {("hue", "1234")}
    assert device.configuration_url == "http://192.168.0.100/config"
    assert device.connections == {(dr.CONNECTION_NETWORK_MAC, "abcd")}
    assert device.entry_type is dr.DeviceEntryType.SERVICE
    assert device.manufacturer == "test-manuf"
    assert device.model == "test-model"
    assert device.name == "test-name"
    assert device.suggested_area == "Heliport"
    assert device.sw_version == "test-sw"
    assert device.hw_version == "test-hw"
    assert device.via_device_id == via.id
async def test_update_entity(hass, client):
    """Test updating entity."""
    registry = mock_registry(
        hass,
        {
            "test_domain.world": RegistryEntry(
                entity_id="test_domain.world",
                unique_id="1234",
                # Using component.async_add_entities is equal to platform "domain"
                platform="test_platform",
                name="before update",
                icon="icon:before update",
            )
        },
    )
    platform = MockEntityPlatform(hass)
    entity = MockEntity(unique_id="1234")
    await platform.async_add_entities([entity])

    state = hass.states.get("test_domain.world")
    assert state is not None
    assert state.name == "before update"
    assert state.attributes[ATTR_ICON] == "icon:before update"

    # UPDATE NAME & ICON & AREA
    await client.send_json(
        {
            "id": 6,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "name": "after update",
            "icon": "icon:after update",
            "area_id": "mock-area-id",
        }
    )

    msg = await client.receive_json()

    assert msg["result"] == {
        "entity_entry": {
            "config_entry_id": None,
            "device_id": None,
            "area_id": "mock-area-id",
            "disabled_by": None,
            "platform": "test_platform",
            "entity_id": "test_domain.world",
            "name": "after update",
            "icon": "icon:after update",
            "original_name": None,
            "original_icon": None,
            "capabilities": None,
            "unique_id": "1234",
        }
    }

    state = hass.states.get("test_domain.world")
    assert state.name == "after update"
    assert state.attributes[ATTR_ICON] == "icon:after update"

    # UPDATE DISABLED_BY TO USER
    await client.send_json(
        {
            "id": 7,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "disabled_by": DISABLED_USER,
        }
    )

    msg = await client.receive_json()

    assert hass.states.get("test_domain.world") is None
    assert registry.entities["test_domain.world"].disabled_by == DISABLED_USER

    # UPDATE DISABLED_BY TO NONE
    await client.send_json(
        {
            "id": 8,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "disabled_by": None,
        }
    )

    msg = await client.receive_json()

    assert msg["result"] == {
        "entity_entry": {
            "config_entry_id": None,
            "device_id": None,
            "area_id": "mock-area-id",
            "disabled_by": None,
            "platform": "test_platform",
            "entity_id": "test_domain.world",
            "name": "after update",
            "icon": "icon:after update",
            "original_name": None,
            "original_icon": None,
            "capabilities": None,
            "unique_id": "1234",
        },
        "reload_delay": 30,
    }
示例#13
0
async def test_update_entity(hass, client):
    """Test updating entity."""
    registry = mock_registry(
        hass,
        {
            "test_domain.world": RegistryEntry(
                entity_id="test_domain.world",
                unique_id="1234",
                # Using component.async_add_entities is equal to platform "domain"
                platform="test_platform",
                name="before update",
            )
        },
    )
    platform = MockEntityPlatform(hass)
    entity = MockEntity(unique_id="1234")
    await platform.async_add_entities([entity])

    state = hass.states.get("test_domain.world")
    assert state is not None
    assert state.name == "before update"

    # UPDATE NAME
    await client.send_json(
        {
            "id": 6,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "name": "after update",
        }
    )

    msg = await client.receive_json()

    assert msg["result"] == {
        "config_entry_id": None,
        "device_id": None,
        "disabled_by": None,
        "platform": "test_platform",
        "entity_id": "test_domain.world",
        "name": "after update",
    }

    state = hass.states.get("test_domain.world")
    assert state.name == "after update"

    # UPDATE DISABLED_BY TO USER
    await client.send_json(
        {
            "id": 7,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "disabled_by": "user",
        }
    )

    msg = await client.receive_json()

    assert hass.states.get("test_domain.world") is None
    assert registry.entities["test_domain.world"].disabled_by == "user"

    # UPDATE DISABLED_BY TO NONE
    await client.send_json(
        {
            "id": 8,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "disabled_by": None,
        }
    )

    msg = await client.receive_json()

    assert msg["result"] == {
        "config_entry_id": None,
        "device_id": None,
        "disabled_by": None,
        "platform": "test_platform",
        "entity_id": "test_domain.world",
        "name": "after update",
    }
示例#14
0
async def test_connected_device_registered(hass):
    """Test dispatch on connected device being registered."""

    registry = mock_registry(hass)
    dispatches = []

    @callback
    def _save_dispatch(msg):
        dispatches.append(msg)

    unsub = async_dispatcher_connect(hass, ce.CONNECTED_DEVICE_REGISTERED,
                                     _save_dispatch)

    class MockScannerEntity(ce.ScannerEntity):
        """Mock a scanner entity."""
        @property
        def ip_address(self) -> str:
            return "5.4.3.2"

        @property
        def unique_id(self) -> str:
            return self.mac_address

    class MockDisconnectedScannerEntity(MockScannerEntity):
        """Mock a disconnected scanner entity."""
        @property
        def mac_address(self) -> str:
            return "aa:bb:cc:dd:ee:ff"

        @property
        def is_connected(self) -> bool:
            return True

        @property
        def hostname(self) -> str:
            return "connected"

    class MockConnectedScannerEntity(MockScannerEntity):
        """Mock a disconnected scanner entity."""
        @property
        def mac_address(self) -> str:
            return "aa:bb:cc:dd:ee:00"

        @property
        def is_connected(self) -> bool:
            return False

        @property
        def hostname(self) -> str:
            return "disconnected"

    async def async_setup_entry(hass, config_entry, async_add_entities):
        """Mock setup entry method."""
        async_add_entities(
            [MockConnectedScannerEntity(),
             MockDisconnectedScannerEntity()])
        return True

    platform = MockPlatform(async_setup_entry=async_setup_entry)
    config_entry = MockConfigEntry(entry_id="super-mock-id")
    entity_platform = MockEntityPlatform(hass,
                                         platform_name=config_entry.domain,
                                         platform=platform)

    assert await entity_platform.async_setup_entry(config_entry)
    await hass.async_block_till_done()
    full_name = f"{entity_platform.domain}.{config_entry.domain}"
    assert full_name in hass.config.components
    assert len(hass.states.async_entity_ids()) == 0  # should be disabled
    assert len(registry.entities) == 2
    assert (registry.entities["test_domain.test_aa_bb_cc_dd_ee_ff"].
            config_entry_id == "super-mock-id")
    unsub()
    assert dispatches == [{
        "ip": "5.4.3.2",
        "mac": "aa:bb:cc:dd:ee:ff",
        "host_name": "connected"
    }]
示例#15
0
async def test_update_entity(hass, client):
    """Test updating entity."""
    registry = mock_registry(
        hass,
        {
            "test_domain.world": RegistryEntry(
                entity_id="test_domain.world",
                unique_id="1234",
                # Using component.async_add_entities is equal to platform "domain"
                platform="test_platform",
                name="before update",
                icon="icon:before update",
            )
        },
    )
    platform = MockEntityPlatform(hass)
    entity = MockEntity(unique_id="1234")
    await platform.async_add_entities([entity])

    state = hass.states.get("test_domain.world")
    assert state is not None
    assert state.name == "before update"
    assert state.attributes[ATTR_ICON] == "icon:before update"

    # UPDATE AREA, DEVICE_CLASS, HIDDEN_BY, ICON AND NAME
    await client.send_json(
        {
            "id": 6,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "area_id": "mock-area-id",
            "device_class": "custom_device_class",
            "hidden_by": "user",  # We exchange strings over the WS API, not enums
            "icon": "icon:after update",
            "name": "after update",
        }
    )

    msg = await client.receive_json()

    assert msg["result"] == {
        "entity_entry": {
            "area_id": "mock-area-id",
            "capabilities": None,
            "config_entry_id": None,
            "device_class": "custom_device_class",
            "device_id": None,
            "disabled_by": None,
            "entity_category": None,
            "entity_id": "test_domain.world",
            "hidden_by": "user",  # We exchange strings over the WS API, not enums
            "icon": "icon:after update",
            "name": "after update",
            "options": {},
            "original_device_class": None,
            "original_icon": None,
            "original_name": None,
            "platform": "test_platform",
            "unique_id": "1234",
        }
    }

    state = hass.states.get("test_domain.world")
    assert state.name == "after update"
    assert state.attributes[ATTR_ICON] == "icon:after update"

    # UPDATE HIDDEN_BY TO ILLEGAL VALUE
    await client.send_json(
        {
            "id": 7,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "hidden_by": "ivy",
        }
    )

    msg = await client.receive_json()
    assert not msg["success"]

    assert registry.entities["test_domain.world"].hidden_by is RegistryEntryHider.USER

    # UPDATE DISABLED_BY TO USER
    await client.send_json(
        {
            "id": 8,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "disabled_by": "user",  # We exchange strings over the WS API, not enums
        }
    )

    msg = await client.receive_json()
    assert msg["success"]

    assert hass.states.get("test_domain.world") is None
    assert (
        registry.entities["test_domain.world"].disabled_by is RegistryEntryDisabler.USER
    )

    # UPDATE DISABLED_BY TO NONE
    await client.send_json(
        {
            "id": 9,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "disabled_by": None,
        }
    )

    msg = await client.receive_json()

    assert msg["result"] == {
        "entity_entry": {
            "area_id": "mock-area-id",
            "capabilities": None,
            "config_entry_id": None,
            "device_class": "custom_device_class",
            "device_id": None,
            "disabled_by": None,
            "entity_category": None,
            "entity_id": "test_domain.world",
            "hidden_by": "user",  # We exchange strings over the WS API, not enums
            "icon": "icon:after update",
            "name": "after update",
            "options": {},
            "original_device_class": None,
            "original_icon": None,
            "original_name": None,
            "platform": "test_platform",
            "unique_id": "1234",
        },
        "reload_delay": 30,
    }

    # UPDATE ENTITY OPTION
    await client.send_json(
        {
            "id": 10,
            "type": "config/entity_registry/update",
            "entity_id": "test_domain.world",
            "options_domain": "sensor",
            "options": {"unit_of_measurement": "beard_second"},
        }
    )

    msg = await client.receive_json()

    assert msg["result"] == {
        "entity_entry": {
            "area_id": "mock-area-id",
            "capabilities": None,
            "config_entry_id": None,
            "device_class": "custom_device_class",
            "device_id": None,
            "disabled_by": None,
            "entity_category": None,
            "entity_id": "test_domain.world",
            "hidden_by": "user",  # We exchange strings over the WS API, not enums
            "icon": "icon:after update",
            "name": "after update",
            "options": {"sensor": {"unit_of_measurement": "beard_second"}},
            "original_device_class": None,
            "original_icon": None,
            "original_name": None,
            "platform": "test_platform",
            "unique_id": "1234",
        },
    }
示例#16
0
async def test_update(hass: HomeAssistant) -> None:
    """Test getting data from the mocked update entity."""
    update = MockUpdateEntity()
    update.hass = hass

    update._attr_installed_version = "1.0.0"
    update._attr_latest_version = "1.0.1"
    update._attr_release_summary = "Summary"
    update._attr_release_url = "https://example.com"
    update._attr_title = "Title"

    assert update.entity_category is EntityCategory.DIAGNOSTIC
    assert update.entity_picture is None
    assert update.installed_version == "1.0.0"
    assert update.latest_version == "1.0.1"
    assert update.release_summary == "Summary"
    assert update.release_url == "https://example.com"
    assert update.title == "Title"
    assert update.in_progress is False
    assert update.state == STATE_ON
    assert update.state_attributes == {
        ATTR_AUTO_UPDATE: False,
        ATTR_INSTALLED_VERSION: "1.0.0",
        ATTR_IN_PROGRESS: False,
        ATTR_LATEST_VERSION: "1.0.1",
        ATTR_RELEASE_SUMMARY: "Summary",
        ATTR_RELEASE_URL: "https://example.com",
        ATTR_SKIPPED_VERSION: None,
        ATTR_TITLE: "Title",
    }

    # Test with platform
    update.platform = MockEntityPlatform(hass)
    assert (
        update.entity_picture
        == "https://brands.home-assistant.io/_/test_platform/icon.png"
    )

    # Test no update available
    update._attr_installed_version = "1.0.0"
    update._attr_latest_version = "1.0.0"
    assert update.state is STATE_OFF

    # Test state becomes unknown if installed version is unknown
    update._attr_installed_version = None
    update._attr_latest_version = "1.0.0"
    assert update.state is None

    # Test state becomes unknown if latest version is unknown
    update._attr_installed_version = "1.0.0"
    update._attr_latest_version = None
    assert update.state is None

    # Test no update if new version is not an update
    update._attr_installed_version = "1.0.0"
    update._attr_latest_version = "0.9.0"
    assert update.state is STATE_OFF

    # Test update if new version is not considered a valid version
    update._attr_installed_version = "1.0.0"
    update._attr_latest_version = "awesome_update"
    assert update.state is STATE_ON

    # Test entity category becomes config when its possible to install
    update._attr_supported_features = UpdateEntityFeature.INSTALL
    assert update.entity_category is EntityCategory.CONFIG

    # UpdateEntityDescription was set
    update._attr_supported_features = 0
    update.entity_description = UpdateEntityDescription(key="F5 - Its very refreshing")
    assert update.device_class is None
    assert update.entity_category is EntityCategory.CONFIG
    update.entity_description = UpdateEntityDescription(
        key="F5 - Its very refreshing",
        device_class=UpdateDeviceClass.FIRMWARE,
        entity_category=None,
    )
    assert update.device_class is UpdateDeviceClass.FIRMWARE
    assert update.entity_category is None

    # Device class via attribute (override entity description)
    update._attr_device_class = None
    assert update.device_class is None
    update._attr_device_class = UpdateDeviceClass.FIRMWARE
    assert update.device_class is UpdateDeviceClass.FIRMWARE

    # Entity Attribute via attribute (override entity description)
    update._attr_entity_category = None
    assert update.entity_category is None
    update._attr_entity_category = EntityCategory.DIAGNOSTIC
    assert update.entity_category is EntityCategory.DIAGNOSTIC

    with pytest.raises(NotImplementedError):
        await update.async_install(version=None, backup=True)

    with pytest.raises(NotImplementedError):
        update.install(version=None, backup=False)

    update.install = MagicMock()
    await update.async_install(version="1.0.1", backup=True)

    assert update.install.called
    assert update.install.call_args[0][0] == "1.0.1"
    assert update.install.call_args[0][1] is True
async def test_passive_bluetooth_entity_with_entity_platform(
    hass, mock_bleak_scanner_start
):
    """Test with a mock entity platform."""
    await async_setup_component(hass, DOMAIN, {DOMAIN: {}})

    entity_platform = MockEntityPlatform(hass)

    @callback
    def _mock_update_method(
        service_info: BluetoothServiceInfo,
    ) -> dict[str, str]:
        return {"test": "data"}

    @callback
    def _async_generate_mock_data(
        data: dict[str, str],
    ) -> PassiveBluetoothDataUpdate:
        """Generate mock data."""
        return NO_DEVICES_PASSIVE_BLUETOOTH_DATA_UPDATE

    coordinator = PassiveBluetoothProcessorCoordinator(
        hass,
        _LOGGER,
        "aa:bb:cc:dd:ee:ff",
        BluetoothScanningMode.ACTIVE,
        _mock_update_method,
    )
    assert coordinator.available is False  # no data yet
    saved_callback = None

    def _async_register_callback(_hass, _callback, _matcher, _mode):
        nonlocal saved_callback
        saved_callback = _callback
        return lambda: None

    processor = PassiveBluetoothDataProcessor(_async_generate_mock_data)
    with patch(
        "homeassistant.components.bluetooth.update_coordinator.async_register_callback",
        _async_register_callback,
    ):
        coordinator.async_register_processor(processor)
        cancel_coordinator = coordinator.async_start()

    processor.async_add_entities_listener(
        PassiveBluetoothProcessorEntity,
        lambda entities: hass.async_create_task(
            entity_platform.async_add_entities(entities)
        ),
    )
    saved_callback(NO_DEVICES_BLUETOOTH_SERVICE_INFO, BluetoothChange.ADVERTISEMENT)
    await hass.async_block_till_done()
    saved_callback(NO_DEVICES_BLUETOOTH_SERVICE_INFO, BluetoothChange.ADVERTISEMENT)
    await hass.async_block_till_done()
    assert (
        hass.states.get("test_domain.test_platform_aa_bb_cc_dd_ee_ff_temperature")
        is not None
    )
    assert (
        hass.states.get("test_domain.test_platform_aa_bb_cc_dd_ee_ff_pressure")
        is not None
    )
    cancel_coordinator()