|
35 | 35 | CONF_BRIGHTNESS_MODE_TIME_DARK, |
36 | 36 | CONF_BRIGHTNESS_MODE_TIME_LIGHT, |
37 | 37 | CONF_DETECT_NON_HA_CHANGES, |
| 38 | + CONF_EXPAND_LIGHT_GROUPS, |
38 | 39 | CONF_INITIAL_TRANSITION, |
39 | 40 | CONF_MANUAL_CONTROL, |
40 | 41 | CONF_MAX_BRIGHTNESS, |
@@ -2386,6 +2387,70 @@ async def test_light_group( |
2386 | 2387 | assert len(events) == 3 |
2387 | 2388 |
|
2388 | 2389 |
|
| 2390 | +async def test_light_group_expand_disabled_off_to_on(hass): |
| 2391 | + """Regression test: off→on reactive adaptation works when expand_light_groups=False. |
| 2392 | +
|
| 2393 | + When expand_light_groups=False the switch stores the group entity in switch.lights. |
| 2394 | + _switches_with_lights must not expand the incoming state-change entity_id either, |
| 2395 | + otherwise the intersection is empty and the switch is never found, silently skipping |
| 2396 | + reactive adaptation. |
| 2397 | + """ |
| 2398 | + await setup_lights(hass, with_group=True) |
| 2399 | + entity_ids = ["light.light_group"] |
| 2400 | + _, switch = await setup_switch( |
| 2401 | + hass, |
| 2402 | + { |
| 2403 | + CONF_LIGHTS: entity_ids, |
| 2404 | + CONF_EXPAND_LIGHT_GROUPS: False, |
| 2405 | + CONF_INITIAL_TRANSITION: 0, |
| 2406 | + CONF_TRANSITION: 0, |
| 2407 | + CONF_INTERCEPT: False, # disable interceptor so reactive path is exercised |
| 2408 | + }, |
| 2409 | + ) |
| 2410 | + await hass.async_block_till_done() |
| 2411 | + |
| 2412 | + assert switch.is_on |
| 2413 | + # With expand disabled, switch.lights should contain the group entity, not children |
| 2414 | + assert "light.light_group" in switch.lights |
| 2415 | + assert "light.light_4" not in switch.lights |
| 2416 | + assert "light.light_5" not in switch.lights |
| 2417 | + |
| 2418 | + # Turn the group off first |
| 2419 | + await hass.services.async_call( |
| 2420 | + LIGHT_DOMAIN, |
| 2421 | + SERVICE_TURN_OFF, |
| 2422 | + {ATTR_ENTITY_ID: "light.light_group"}, |
| 2423 | + blocking=True, |
| 2424 | + ) |
| 2425 | + await hass.async_block_till_done() |
| 2426 | + |
| 2427 | + # Track adaptation calls triggered by the off→on event |
| 2428 | + adapted = [] |
| 2429 | + original = switch._respond_to_off_to_on_event |
| 2430 | + |
| 2431 | + async def track_adapt(entity_id, event): |
| 2432 | + adapted.append(entity_id) |
| 2433 | + return await original(entity_id, event) |
| 2434 | + |
| 2435 | + switch._respond_to_off_to_on_event = track_adapt |
| 2436 | + |
| 2437 | + # Turn the group back on from OFF — this fires a state_changed event for |
| 2438 | + # "light.light_group"; the reactive path must find the switch via this entity. |
| 2439 | + await hass.services.async_call( |
| 2440 | + LIGHT_DOMAIN, |
| 2441 | + SERVICE_TURN_ON, |
| 2442 | + {ATTR_ENTITY_ID: "light.light_group"}, |
| 2443 | + blocking=True, |
| 2444 | + ) |
| 2445 | + await hass.async_block_till_done() |
| 2446 | + await asyncio.gather(*switch.manager.adaptation_tasks) |
| 2447 | + |
| 2448 | + assert "light.light_group" in adapted, ( |
| 2449 | + "Switch was not found via _switches_with_lights for the group entity " |
| 2450 | + "when expand_light_groups=False — reactive off→on adaptation was skipped." |
| 2451 | + ) |
| 2452 | + |
| 2453 | + |
2389 | 2454 | @pytest.mark.parametrize("brightness_mode", ["linear", "tanh"]) |
2390 | 2455 | @pytest.mark.parametrize(("dark", "light"), ([900, 1800], [1800, 900], [1800, 1800])) |
2391 | 2456 | async def test_brightness_mode(hass, brightness_mode, dark, light): |
|
0 commit comments