mirror of
https://github.com/esphome/esphome.git
synced 2025-08-06 18:37:47 +00:00
empty name uses device name, use get_base_entity_object_id
This commit is contained in:
parent
b7d0f5e36b
commit
07f361a404
@ -187,8 +187,17 @@ def entity_duplicate_validator(platform: str) -> Callable[[ConfigType], ConfigTy
|
||||
# Get the entity name
|
||||
entity_name = config[CONF_NAME]
|
||||
|
||||
# For duplicate detection, just use the sanitized name
|
||||
name_key = sanitize(snake_case(entity_name))
|
||||
# Get device name if entity is on a sub-device
|
||||
device_name = None
|
||||
if CONF_DEVICE_ID in config:
|
||||
device_id_obj = config[CONF_DEVICE_ID]
|
||||
device_name = device_id_obj.id
|
||||
|
||||
# Calculate what object_id will actually be used
|
||||
# This handles empty names correctly by using device/friendly names
|
||||
name_key = get_base_entity_object_id(
|
||||
entity_name, CORE.friendly_name, device_name
|
||||
)
|
||||
|
||||
# Check for duplicates
|
||||
unique_key = (platform, name_key)
|
||||
|
@ -133,7 +133,35 @@ button:
|
||||
name: "Reset Main"
|
||||
on_press: [] # Main device
|
||||
|
||||
# Scenario 6: Special characters in names - now with unique names
|
||||
# Scenario 6: Empty names (should use device names)
|
||||
select:
|
||||
- platform: template
|
||||
name: ""
|
||||
device_id: controller_1
|
||||
options:
|
||||
- "Option 1"
|
||||
- "Option 2"
|
||||
lambda: return {"Option 1"};
|
||||
set_action: []
|
||||
|
||||
- platform: template
|
||||
name: ""
|
||||
device_id: controller_2
|
||||
options:
|
||||
- "Option 1"
|
||||
- "Option 2"
|
||||
lambda: return {"Option 1"};
|
||||
set_action: []
|
||||
|
||||
- platform: template
|
||||
name: "" # Main device
|
||||
options:
|
||||
- "Option 1"
|
||||
- "Option 2"
|
||||
lambda: return {"Option 1"};
|
||||
set_action: []
|
||||
|
||||
# Scenario 7: Special characters in names - now with unique names
|
||||
number:
|
||||
- platform: template
|
||||
name: "Temperature Setpoint! Controller 1"
|
||||
|
@ -52,6 +52,7 @@ async def test_duplicate_entities_not_allowed_on_different_devices(
|
||||
switches = [e for e in all_entities if e.__class__.__name__ == "SwitchInfo"]
|
||||
buttons = [e for e in all_entities if e.__class__.__name__ == "ButtonInfo"]
|
||||
numbers = [e for e in all_entities if e.__class__.__name__ == "NumberInfo"]
|
||||
selects = [e for e in all_entities if e.__class__.__name__ == "SelectInfo"]
|
||||
|
||||
# Scenario 1: Check that temperature sensors have unique names per device
|
||||
temp_sensors = [s for s in sensors if "Temperature" in s.name]
|
||||
@ -144,7 +145,28 @@ async def test_duplicate_entities_not_allowed_on_different_devices(
|
||||
f"Reset buttons should have unique names, got {reset_names}"
|
||||
)
|
||||
|
||||
# Scenario 7: Check special characters in number names - now unique
|
||||
# Scenario 7: Check empty name selects (should use device names)
|
||||
empty_selects = [s for s in selects if s.name == ""]
|
||||
assert len(empty_selects) == 3, (
|
||||
f"Expected exactly 3 empty name selects, got {len(empty_selects)}"
|
||||
)
|
||||
|
||||
# Group by device
|
||||
c1_selects = [s for s in empty_selects if s.device_id == controller_1.device_id]
|
||||
c2_selects = [s for s in empty_selects if s.device_id == controller_2.device_id]
|
||||
|
||||
# For main device, device_id is 0
|
||||
main_selects = [s for s in empty_selects if s.device_id == 0]
|
||||
|
||||
# Check object IDs for empty name entities - they should use device names
|
||||
assert len(c1_selects) == 1 and c1_selects[0].object_id == "controller_1"
|
||||
assert len(c2_selects) == 1 and c2_selects[0].object_id == "controller_2"
|
||||
assert (
|
||||
len(main_selects) == 1
|
||||
and main_selects[0].object_id == "duplicate-entities-test"
|
||||
)
|
||||
|
||||
# Scenario 8: Check special characters in number names - now unique
|
||||
temp_numbers = [n for n in numbers if "Temperature Setpoint!" in n.name]
|
||||
assert len(temp_numbers) == 2, (
|
||||
f"Expected exactly 2 temperature setpoint numbers, got {len(temp_numbers)}"
|
||||
@ -170,6 +192,7 @@ async def test_duplicate_entities_not_allowed_on_different_devices(
|
||||
+ len(switches)
|
||||
+ len(buttons)
|
||||
+ len(numbers)
|
||||
+ len(selects)
|
||||
)
|
||||
|
||||
def on_state(state) -> None:
|
||||
|
@ -555,6 +555,17 @@ def test_entity_duplicate_validator_with_devices() -> None:
|
||||
assert validated3 == config3
|
||||
assert ("sensor", "humidity") in CORE.unique_ids
|
||||
|
||||
# Empty names should use device names and be allowed
|
||||
config4 = {CONF_NAME: "", CONF_DEVICE_ID: device1}
|
||||
validated4 = validator(config4)
|
||||
assert validated4 == config4
|
||||
assert ("sensor", "device1") in CORE.unique_ids
|
||||
|
||||
config5 = {CONF_NAME: "", CONF_DEVICE_ID: device2}
|
||||
validated5 = validator(config5)
|
||||
assert validated5 == config5
|
||||
assert ("sensor", "device2") in CORE.unique_ids
|
||||
|
||||
|
||||
def test_duplicate_entity_yaml_validation(
|
||||
yaml_file: Callable[[str], str], capsys: pytest.CaptureFixture[str]
|
||||
|
Loading…
x
Reference in New Issue
Block a user